UEsDBAoAAAAAAAAAIQAmbx6fMgAAADIAAAAUAAAATUVUQS1JTkYvTUFOSUZFU1QuTUZNYW5pZmVzdC1WZXJzaW9uOiAxLjAKQ3JlYXRlZC1CeTogMS42LjAgKHByb3RvYykKClBLAwQKAAAAAAAAACEAOS6iSspcAADKXAAAKwAAAGNvbS9nb29nbGUvcHJvdG9idWYvVW5pdHRlc3RJbXBvcnRMaXRlLmphdmEvLyBHZW5lcmF0ZWQgYnkgdGhlIHByb3RvY29sIGJ1ZmZlciBjb21waWxlci4gIERPIE5PVCBFRElUIQovLyBzb3VyY2U6IGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9pbXBvcnRfbGl0ZS5wcm90bwoKLy8gUHJvdG9idWYgSmF2YSBWZXJzaW9uOiAzLjI1LjAKcGFja2FnZSBjb20uZ29vZ2xlLnByb3RvYnVmOwoKcHVibGljIGZpbmFsIGNsYXNzIFVuaXR0ZXN0SW1wb3J0TGl0ZSB7CiAgcHJpdmF0ZSBVbml0dGVzdEltcG9ydExpdGUoKSB7fQogIHB1YmxpYyBzdGF0aWMgdm9pZCByZWdpc3RlckFsbEV4dGVuc2lvbnMoCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIHJlZ2lzdHJ5KSB7CiAgfQoKICBwdWJsaWMgc3RhdGljIHZvaWQgcmVnaXN0ZXJBbGxFeHRlbnNpb25zKAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5IHJlZ2lzdHJ5KSB7CiAgICByZWdpc3RlckFsbEV4dGVuc2lvbnMoCiAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlKSByZWdpc3RyeSk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIGVudW0ge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZX0KICAgKi8KICBwdWJsaWMgZW51bSBJbXBvcnRFbnVtTGl0ZQogICAgICBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xNZXNzYWdlRW51bSB7CiAgICAvKioKICAgICAqIDxjb2RlPklNUE9SVF9MSVRFX0ZPTyA9IDc7PC9jb2RlPgogICAgICovCiAgICBJTVBPUlRfTElURV9GT08oNyksCiAgICAvKioKICAgICAqIDxjb2RlPklNUE9SVF9MSVRFX0JBUiA9IDg7PC9jb2RlPgogICAgICovCiAgICBJTVBPUlRfTElURV9CQVIoOCksCiAgICAvKioKICAgICAqIDxjb2RlPklNUE9SVF9MSVRFX0JBWiA9IDk7PC9jb2RlPgogICAgICovCiAgICBJTVBPUlRfTElURV9CQVooOSksCiAgICA7CgogICAgLyoqCiAgICAgKiA8Y29kZT5JTVBPUlRfTElURV9GT08gPSA3OzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgSU1QT1JUX0xJVEVfRk9PX1ZBTFVFID0gNzsKICAgIC8qKgogICAgICogPGNvZGU+SU1QT1JUX0xJVEVfQkFSID0gODs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IElNUE9SVF9MSVRFX0JBUl9WQUxVRSA9IDg7CiAgICAvKioKICAgICAqIDxjb2RlPklNUE9SVF9MSVRFX0JBWiA9IDk7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBJTVBPUlRfTElURV9CQVpfVkFMVUUgPSA5OwoKCiAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgc3RhdGljIEltcG9ydEVudW1MaXRlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgIHJldHVybiBmb3JOdW1iZXIodmFsdWUpOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgSW1wb3J0RW51bUxpdGUgZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICBzd2l0Y2ggKHZhbHVlKSB7CiAgICAgICAgY2FzZSA3OiByZXR1cm4gSU1QT1JUX0xJVEVfRk9POwogICAgICAgIGNhc2UgODogcmV0dXJuIElNUE9SVF9MSVRFX0JBUjsKICAgICAgICBjYXNlIDk6IHJldHVybiBJTVBPUlRfTElURV9CQVo7CiAgICAgICAgZGVmYXVsdDogcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8SW1wb3J0RW51bUxpdGU+CiAgICAgICAgaW50ZXJuYWxHZXRWYWx1ZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsVmFsdWVNYXA7CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPAogICAgICAgIEltcG9ydEVudW1MaXRlPiBpbnRlcm5hbFZhbHVlTWFwID0KICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPEltcG9ydEVudW1MaXRlPigpIHsKICAgICAgICAgICAgcHVibGljIEltcG9ydEVudW1MaXRlIGZpbmRWYWx1ZUJ5TnVtYmVyKGludCBudW1iZXIpIHsKICAgICAgICAgICAgICByZXR1cm4gSW1wb3J0RW51bUxpdGUuZm9yTnVtYmVyKG51bWJlcik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CgogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvcgogICAgICAgIGdldFZhbHVlRGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKS5nZXRWYWx1ZXMoKS5nZXQob3JkaW5hbCgpKTsKICAgIH0KICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuZ2V0RGVzY3JpcHRvcigpLmdldEVudW1UeXBlcygpLmdldCgwKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBJbXBvcnRFbnVtTGl0ZVtdIFZBTFVFUyA9IHZhbHVlcygpOwoKICAgIHB1YmxpYyBzdGF0aWMgSW1wb3J0RW51bUxpdGUgdmFsdWVPZigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IgZGVzYykgewogICAgICBpZiAoZGVzYy5nZXRUeXBlKCkgIT0gZ2V0RGVzY3JpcHRvcigpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAiRW51bVZhbHVlRGVzY3JpcHRvciBpcyBub3QgZm9yIHRoaXMgdHlwZS4iKTsKICAgICAgfQogICAgICByZXR1cm4gVkFMVUVTW2Rlc2MuZ2V0SW5kZXgoKV07CiAgICB9CgogICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CgogICAgcHJpdmF0ZSBJbXBvcnRFbnVtTGl0ZShpbnQgdmFsdWUpIHsKICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChlbnVtX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSkKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZCA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGQgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGQuCiAgICAgKi8KICAgIGludCBnZXREKCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEltcG9ydE1lc3NhZ2VMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSkKICAgICAgSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIEltcG9ydE1lc3NhZ2VMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIEltcG9ydE1lc3NhZ2VMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgSW1wb3J0TWVzc2FnZUxpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgSW1wb3J0TWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X0ltcG9ydE1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9JbXBvcnRNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRF9GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBpbnQgZF8gPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGQgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0RCgpIHsKICAgICAgcmV0dXJuIGRfOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMSwgZF8pOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDEsIGRfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUpIG9iajsKCiAgICAgIGlmIChoYXNEKCkgIT0gb3RoZXIuaGFzRCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEKCkpIHsKICAgICAgICBpZiAoZ2V0RCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldEQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0QoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEQoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9JbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X0ltcG9ydE1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBkXyA9IDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfSW1wb3J0TWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kXyA9IGRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzRCgpKSB7CiAgICAgICAgICBzZXREKG90aGVyLmdldEQoKSk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgODogewogICAgICAgICAgICAgICAgZF8gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IGRfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXREKCkgewogICAgICAgIHJldHVybiBkXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZCA9IDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREKGludCB2YWx1ZSkgewoKICAgICAgICBkXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZCA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGRfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPEltcG9ydE1lc3NhZ2VMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPEltcG9ydE1lc3NhZ2VMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxJbXBvcnRNZXNzYWdlTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxJbXBvcnRNZXNzYWdlTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X0ltcG9ydE1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9JbXBvcnRNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CgogIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgcmV0dXJuIGRlc2NyaXB0b3I7CiAgfQogIHByaXZhdGUgc3RhdGljICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIGRlc2NyaXB0b3I7CiAgc3RhdGljIHsKICAgIGphdmEubGFuZy5TdHJpbmdbXSBkZXNjcmlwdG9yRGF0YSA9IHsKICAgICAgIlxuKmdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9pbXBvcnRfbGl0ZS5wIiArCiAgICAgICJyb3RvXDAyMlwwMzBwcm90b2J1Zl91bml0dGVzdF9pbXBvcnRcMDMyMWdvb2dsZS9wIiArCiAgICAgICJyb3RvYnVmL3VuaXR0ZXN0X2ltcG9ydF9wdWJsaWNfbGl0ZS5wcm90IiArCiAgICAgICJvXCJcMDM2XG5cMDIxSW1wb3J0TWVzc2FnZUxpdGVcMDIyXHRcblwwMDFkXDAzMFwwMDEgXDAwMShcMDA1Kk9cblwwMTZJbXAiICsKICAgICAgIm9ydEVudW1MaXRlXDAyMlwwMjNcblwwMTdJTVBPUlRfTElURV9GT09cMDIwXDAwN1wwMjJcMDIzXG5cMDE3SU1QTyIgKwogICAgICAiUlRfTElURV9CQVJcMDIwXDAxMFwwMjJcMDIzXG5cMDE3SU1QT1JUX0xJVEVfQkFaXDAyMFx0QlwwMjdcblwwMjNjbyIgKwogICAgICAibS5nb29nbGUucHJvdG9idWZIXDAwM1BcMDAwIgogICAgfTsKICAgIGRlc2NyaXB0b3IgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIC5pbnRlcm5hbEJ1aWxkR2VuZXJhdGVkRmlsZUZyb20oZGVzY3JpcHRvckRhdGEsCiAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3JbXSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5nZXREZXNjcmlwdG9yKCksCiAgICAgICAgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X0ltcG9ydE1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9JbXBvcnRNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfSW1wb3J0TWVzc2FnZUxpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkQiLCB9KTsKICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLmdldERlc2NyaXB0b3IoKTsKICB9CgogIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChvdXRlcl9jbGFzc19zY29wZSkKfQpQSwMECgAAAAAAAAAhAOFJJdf0UQAA9FEAADEAAABjb20vZ29vZ2xlL3Byb3RvYnVmL1VuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5qYXZhLy8gR2VuZXJhdGVkIGJ5IHRoZSBwcm90b2NvbCBidWZmZXIgY29tcGlsZXIuICBETyBOT1QgRURJVCEKLy8gc291cmNlOiBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19saXRlLnByb3RvCgovLyBQcm90b2J1ZiBKYXZhIFZlcnNpb246IDMuMjUuMApwYWNrYWdlIGNvbS5nb29nbGUucHJvdG9idWY7CgpwdWJsaWMgZmluYWwgY2xhc3MgVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlIHsKICBwcml2YXRlIFVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZSgpIHt9CiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgcmVnaXN0cnkpIHsKICB9CgogIHB1YmxpYyBzdGF0aWMgdm9pZCByZWdpc3RlckFsbEV4dGVuc2lvbnMoCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnkgcmVnaXN0cnkpIHsKICAgIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUpIHJlZ2lzdHJ5KTsKICB9CiAgcHVibGljIGludGVyZmFjZSBQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBlID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGUgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZS4KICAgICAqLwogICAgaW50IGdldEUoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKQogICAgICBQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgUHVibGljSW1wb3J0TWVzc2FnZUxpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgUHVibGljSW1wb3J0TWVzc2FnZUxpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfUHVibGljSW1wb3J0TWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X1B1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIGludCBlXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGUgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0UoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRFKCkgewogICAgICByZXR1cm4gZV87CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigxLCBlXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMSwgZV8pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc0UoKSAhPSBvdGhlci5oYXNFKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0UoKSkgewogICAgICAgIGlmIChnZXRFKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoaGFzRSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X1B1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfUHVibGljSW1wb3J0TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGVfID0gMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmVfID0gZV87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNFKCkpIHsKICAgICAgICAgIHNldEUob3RoZXIuZ2V0RSgpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICBlXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBpbnQgZV8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZSA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGUgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNFKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZSA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBlLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEUoKSB7CiAgICAgICAgcmV0dXJuIGVfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBlID0gMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEUoaW50IHZhbHVlKSB7CgogICAgICAgIGVfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBlID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgZV8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UHVibGljSW1wb3J0TWVzc2FnZUxpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UHVibGljSW1wb3J0TWVzc2FnZUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfUHVibGljSW1wb3J0TWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X1B1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKCiAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICByZXR1cm4gZGVzY3JpcHRvcjsKICB9CiAgcHJpdmF0ZSBzdGF0aWMgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3IKICAgICAgZGVzY3JpcHRvcjsKICBzdGF0aWMgewogICAgamF2YS5sYW5nLlN0cmluZ1tdIGRlc2NyaXB0b3JEYXRhID0gewogICAgICAiXG4xZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2ltcG9ydF9wdWJsaWMiICsKICAgICAgIl9saXRlLnByb3RvXDAyMlwwMzBwcm90b2J1Zl91bml0dGVzdF9pbXBvcnRcIiRcbiIgKwogICAgICAiXDAyN1B1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlXDAyMlx0XG5cMDAxZVwwMzBcMDAxIFwwMDEoXDAwNUJcMDI3XG5cMDIzYyIgKwogICAgICAib20uZ29vZ2xlLnByb3RvYnVmSFwwMDMiCiAgICB9OwogICAgZGVzY3JpcHRvciA9IGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3IKICAgICAgLmludGVybmFsQnVpbGRHZW5lcmF0ZWRGaWxlRnJvbShkZXNjcmlwdG9yRGF0YSwKICAgICAgICBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcltdIHsKICAgICAgICB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfUHVibGljSW1wb3J0TWVzc2FnZUxpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X1B1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiRSIsIH0pOwogIH0KCiAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG91dGVyX2NsYXNzX3Njb3BlKQp9ClBLAwQKAAAAAAAAACEAhKMEGT6kGgA+pBoAJQAAAGNvbS9nb29nbGUvcHJvdG9idWYvVW5pdHRlc3RMaXRlLmphdmEvLyBHZW5lcmF0ZWQgYnkgdGhlIHByb3RvY29sIGJ1ZmZlciBjb21waWxlci4gIERPIE5PVCBFRElUIQovLyBzb3VyY2U6IGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvCgovLyBQcm90b2J1ZiBKYXZhIFZlcnNpb246IDMuMjUuMApwYWNrYWdlIGNvbS5nb29nbGUucHJvdG9idWY7CgpwdWJsaWMgZmluYWwgY2xhc3MgVW5pdHRlc3RMaXRlIHsKICBwcml2YXRlIFVuaXR0ZXN0TGl0ZSgpIHt9CiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgcmVnaXN0cnkpIHsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEludDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxJbnQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsVWludDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxVaW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbFNpbnQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsU2ludDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxGaXhlZDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxGaXhlZDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxTZml4ZWQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsU2ZpeGVkNjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEZsb2F0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxEb3VibGVFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEJvb2xFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbFN0cmluZ0V4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsQnl0ZXNFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEdyb3VwRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxOZXN0ZWRNZXNzYWdlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxGb3JlaWduTWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsSW1wb3J0TWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsTmVzdGVkRW51bUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsRm9yZWlnbkVudW1FeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEltcG9ydEVudW1FeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbFN0cmluZ1BpZWNlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxDb3JkRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxMYXp5TWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRJbnQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkSW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZFVpbnQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkVWludDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRTaW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZFNpbnQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkRml4ZWQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkRml4ZWQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkU2ZpeGVkMzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRGbG9hdEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkRG91YmxlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRCb29sRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRTdHJpbmdFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZEJ5dGVzRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRHcm91cEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkTmVzdGVkTWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZEltcG9ydE1lc3NhZ2VFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZE5lc3RlZEVudW1FeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZEZvcmVpZ25FbnVtRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRJbXBvcnRFbnVtRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRTdHJpbmdQaWVjZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkQ29yZEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkTGF6eU1lc3NhZ2VFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0SW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0SW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0VWludDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZGVmYXVsdFVpbnQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRTaW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0U2ludDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZGVmYXVsdEZpeGVkMzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0Rml4ZWQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRTZml4ZWQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRTZml4ZWQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRGbG9hdEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHREb3VibGVFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0Qm9vbEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRTdHJpbmdFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0Qnl0ZXNFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0TmVzdGVkRW51bUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRGb3JlaWduRW51bUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRJbXBvcnRFbnVtRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZGVmYXVsdFN0cmluZ1BpZWNlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZGVmYXVsdENvcmRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vbmVvZlVpbnQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9uZW9mTmVzdGVkTWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9uZW9mU3RyaW5nRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub25lb2ZCeXRlc0V4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnBhY2tlZEludDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucGFja2VkSW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRVaW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRVaW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRTaW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRTaW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRGaXhlZDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucGFja2VkRml4ZWQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnBhY2tlZFNmaXhlZDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucGFja2VkU2ZpeGVkNjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRGbG9hdEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnBhY2tlZERvdWJsZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnBhY2tlZEJvb2xFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRFbnVtRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUudGVzdEFsbFR5cGVzTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUubmVzdGVkRXh0ZW5zaW9uKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5vcHRpb25hbEV4dCk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUucmVwZWF0ZWRFeHQpOwogIH0KCiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeSByZWdpc3RyeSkgewogICAgcmVnaXN0ZXJBbGxFeHRlbnNpb25zKAogICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSkgcmVnaXN0cnkpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiBlbnVtIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlfQogICAqLwogIHB1YmxpYyBlbnVtIEZvcmVpZ25FbnVtTGl0ZQogICAgICBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xNZXNzYWdlRW51bSB7CiAgICAvKioKICAgICAqIDxjb2RlPkZPUkVJR05fTElURV9GT08gPSA0OzwvY29kZT4KICAgICAqLwogICAgRk9SRUlHTl9MSVRFX0ZPTyg0KSwKICAgIC8qKgogICAgICogPGNvZGU+Rk9SRUlHTl9MSVRFX0JBWiA9IDY7PC9jb2RlPgogICAgICovCiAgICBGT1JFSUdOX0xJVEVfQkFaKDYpLAogICAgLyoqCiAgICAgKiA8Y29kZT5GT1JFSUdOX0xJVEVfQkFSID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIEZPUkVJR05fTElURV9CQVIoNSksCiAgICA7CgogICAgLyoqCiAgICAgKiA8Y29kZT5GT1JFSUdOX0xJVEVfRk9PID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZPUkVJR05fTElURV9GT09fVkFMVUUgPSA0OwogICAgLyoqCiAgICAgKiA8Y29kZT5GT1JFSUdOX0xJVEVfQkFaID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZPUkVJR05fTElURV9CQVpfVkFMVUUgPSA2OwogICAgLyoqCiAgICAgKiA8Y29kZT5GT1JFSUdOX0xJVEVfQkFSID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZPUkVJR05fTElURV9CQVJfVkFMVUUgPSA1OwoKCiAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgc3RhdGljIEZvcmVpZ25FbnVtTGl0ZSB2YWx1ZU9mKGludCB2YWx1ZSkgewogICAgICByZXR1cm4gZm9yTnVtYmVyKHZhbHVlKTsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIEZvcmVpZ25FbnVtTGl0ZSBmb3JOdW1iZXIoaW50IHZhbHVlKSB7CiAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICBjYXNlIDQ6IHJldHVybiBGT1JFSUdOX0xJVEVfRk9POwogICAgICAgIGNhc2UgNjogcmV0dXJuIEZPUkVJR05fTElURV9CQVo7CiAgICAgICAgY2FzZSA1OiByZXR1cm4gRk9SRUlHTl9MSVRFX0JBUjsKICAgICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxGb3JlaWduRW51bUxpdGU+CiAgICAgICAgaW50ZXJuYWxHZXRWYWx1ZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsVmFsdWVNYXA7CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPAogICAgICAgIEZvcmVpZ25FbnVtTGl0ZT4gaW50ZXJuYWxWYWx1ZU1hcCA9CiAgICAgICAgICBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxGb3JlaWduRW51bUxpdGU+KCkgewogICAgICAgICAgICBwdWJsaWMgRm9yZWlnbkVudW1MaXRlIGZpbmRWYWx1ZUJ5TnVtYmVyKGludCBudW1iZXIpIHsKICAgICAgICAgICAgICByZXR1cm4gRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcihudW1iZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IKICAgICAgICBnZXRWYWx1ZURlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCkuZ2V0VmFsdWVzKCkuZ2V0KG9yZGluYWwoKSk7CiAgICB9CiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMCk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgRm9yZWlnbkVudW1MaXRlW10gVkFMVUVTID0gdmFsdWVzKCk7CgogICAgcHVibGljIHN0YXRpYyBGb3JlaWduRW51bUxpdGUgdmFsdWVPZigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IgZGVzYykgewogICAgICBpZiAoZGVzYy5nZXRUeXBlKCkgIT0gZ2V0RGVzY3JpcHRvcigpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAiRW51bVZhbHVlRGVzY3JpcHRvciBpcyBub3QgZm9yIHRoaXMgdHlwZS4iKTsKICAgICAgfQogICAgICByZXR1cm4gVkFMVUVTW2Rlc2MuZ2V0SW5kZXgoKV07CiAgICB9CgogICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CgogICAgcHJpdmF0ZSBGb3JlaWduRW51bUxpdGUoaW50IHZhbHVlKSB7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlKQogIH0KCiAgLyoqCiAgICogUHJvdG9idWYgZW51bSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlYxRW51bUxpdGV9CiAgICovCiAgcHVibGljIGVudW0gVjFFbnVtTGl0ZQogICAgICBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xNZXNzYWdlRW51bSB7CiAgICAvKioKICAgICAqIDxjb2RlPlYxX0ZJUlNUID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIFYxX0ZJUlNUKDEpLAogICAgOwoKICAgIC8qKgogICAgICogPGNvZGU+VjFfRklSU1QgPSAxOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgVjFfRklSU1RfVkFMVUUgPSAxOwoKCiAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgc3RhdGljIFYxRW51bUxpdGUgdmFsdWVPZihpbnQgdmFsdWUpIHsKICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBWMUVudW1MaXRlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgIGNhc2UgMTogcmV0dXJuIFYxX0ZJUlNUOwogICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPFYxRW51bUxpdGU+CiAgICAgICAgaW50ZXJuYWxHZXRWYWx1ZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsVmFsdWVNYXA7CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPAogICAgICAgIFYxRW51bUxpdGU+IGludGVybmFsVmFsdWVNYXAgPQogICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8VjFFbnVtTGl0ZT4oKSB7CiAgICAgICAgICAgIHB1YmxpYyBWMUVudW1MaXRlIGZpbmRWYWx1ZUJ5TnVtYmVyKGludCBudW1iZXIpIHsKICAgICAgICAgICAgICByZXR1cm4gVjFFbnVtTGl0ZS5mb3JOdW1iZXIobnVtYmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKCiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yCiAgICAgICAgZ2V0VmFsdWVEZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpLmdldFZhbHVlcygpLmdldChvcmRpbmFsKCkpOwogICAgfQogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5nZXREZXNjcmlwdG9yKCkuZ2V0RW51bVR5cGVzKCkuZ2V0KDEpOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIFYxRW51bUxpdGVbXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICBwdWJsaWMgc3RhdGljIFYxRW51bUxpdGUgdmFsdWVPZigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IgZGVzYykgewogICAgICBpZiAoZGVzYy5nZXRUeXBlKCkgIT0gZ2V0RGVzY3JpcHRvcigpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAiRW51bVZhbHVlRGVzY3JpcHRvciBpcyBub3QgZm9yIHRoaXMgdHlwZS4iKTsKICAgICAgfQogICAgICByZXR1cm4gVkFMVUVTW2Rlc2MuZ2V0SW5kZXgoKV07CiAgICB9CgogICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CgogICAgcHJpdmF0ZSBWMUVudW1MaXRlKGludCB2YWx1ZSkgewogICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGVudW1fc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlYxRW51bUxpdGUpCiAgfQoKICAvKioKICAgKiBQcm90b2J1ZiBlbnVtIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVjJFbnVtTGl0ZX0KICAgKi8KICBwdWJsaWMgZW51bSBWMkVudW1MaXRlCiAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Qcm90b2NvbE1lc3NhZ2VFbnVtIHsKICAgIC8qKgogICAgICogPGNvZGU+VjJfRklSU1QgPSAxOzwvY29kZT4KICAgICAqLwogICAgVjJfRklSU1QoMSksCiAgICAvKioKICAgICAqIDxjb2RlPlYyX1NFQ09ORCA9IDI7PC9jb2RlPgogICAgICovCiAgICBWMl9TRUNPTkQoMiksCiAgICA7CgogICAgLyoqCiAgICAgKiA8Y29kZT5WMl9GSVJTVCA9IDE7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBWMl9GSVJTVF9WQUxVRSA9IDE7CiAgICAvKioKICAgICAqIDxjb2RlPlYyX1NFQ09ORCA9IDI7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBWMl9TRUNPTkRfVkFMVUUgPSAyOwoKCiAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgc3RhdGljIFYyRW51bUxpdGUgdmFsdWVPZihpbnQgdmFsdWUpIHsKICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBWMkVudW1MaXRlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgIGNhc2UgMTogcmV0dXJuIFYyX0ZJUlNUOwogICAgICAgIGNhc2UgMjogcmV0dXJuIFYyX1NFQ09ORDsKICAgICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxWMkVudW1MaXRlPgogICAgICAgIGludGVybmFsR2V0VmFsdWVNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbFZhbHVlTWFwOwogICAgfQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDwKICAgICAgICBWMkVudW1MaXRlPiBpbnRlcm5hbFZhbHVlTWFwID0KICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPFYyRW51bUxpdGU+KCkgewogICAgICAgICAgICBwdWJsaWMgVjJFbnVtTGl0ZSBmaW5kVmFsdWVCeU51bWJlcihpbnQgbnVtYmVyKSB7CiAgICAgICAgICAgICAgcmV0dXJuIFYyRW51bUxpdGUuZm9yTnVtYmVyKG51bWJlcik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CgogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvcgogICAgICAgIGdldFZhbHVlRGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKS5nZXRWYWx1ZXMoKS5nZXQob3JkaW5hbCgpKTsKICAgIH0KICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZ2V0RGVzY3JpcHRvcigpLmdldEVudW1UeXBlcygpLmdldCgyKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBWMkVudW1MaXRlW10gVkFMVUVTID0gdmFsdWVzKCk7CgogICAgcHVibGljIHN0YXRpYyBWMkVudW1MaXRlIHZhbHVlT2YoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yIGRlc2MpIHsKICAgICAgaWYgKGRlc2MuZ2V0VHlwZSgpICE9IGdldERlc2NyaXB0b3IoKSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKAogICAgICAgICAgIkVudW1WYWx1ZURlc2NyaXB0b3IgaXMgbm90IGZvciB0aGlzIHR5cGUuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIFZBTFVFU1tkZXNjLmdldEluZGV4KCldOwogICAgfQoKICAgIHByaXZhdGUgZmluYWwgaW50IHZhbHVlOwoKICAgIHByaXZhdGUgVjJFbnVtTGl0ZShpbnQgdmFsdWUpIHsKICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChlbnVtX3Njb3BlOnByb3RvMl91bml0dGVzdC5WMkVudW1MaXRlKQogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFNpbmd1bGFyCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBvcHRpb25hbF9pbnQzMiA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEludDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEludDMyKCk7CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBTaW5ndWxhcgogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW50MzIuCiAgICAgKi8KICAgIGludCBnZXRPcHRpb25hbEludDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBvcHRpb25hbF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEludDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEludDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IG9wdGlvbmFsX2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEludDY0LgogICAgICovCiAgICBsb25nIGdldE9wdGlvbmFsSW50NjQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBvcHRpb25hbF91aW50MzIgPSAzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsVWludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBvcHRpb25hbF91aW50MzIgPSAzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsVWludDMyLgogICAgICovCiAgICBpbnQgZ2V0T3B0aW9uYWxVaW50MzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQ2NCBvcHRpb25hbF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxVaW50NjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsVWludDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQ2NCBvcHRpb25hbF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsVWludDY0LgogICAgICovCiAgICBsb25nIGdldE9wdGlvbmFsVWludDY0KCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgb3B0aW9uYWxfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU2ludDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbFNpbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgb3B0aW9uYWxfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFNpbnQzMi4KICAgICAqLwogICAgaW50IGdldE9wdGlvbmFsU2ludDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50NjQgb3B0aW9uYWxfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU2ludDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbFNpbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50NjQgb3B0aW9uYWxfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFNpbnQ2NC4KICAgICAqLwogICAgbG9uZyBnZXRPcHRpb25hbFNpbnQ2NCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBvcHRpb25hbF9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRml4ZWQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxGaXhlZDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkMzIgb3B0aW9uYWxfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxGaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0T3B0aW9uYWxGaXhlZDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IG9wdGlvbmFsX2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxGaXhlZDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEZpeGVkNjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQ2NCBvcHRpb25hbF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZpeGVkNjQuCiAgICAgKi8KICAgIGxvbmcgZ2V0T3B0aW9uYWxGaXhlZDY0KCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQzMiBvcHRpb25hbF9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFNmaXhlZDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbFNmaXhlZDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIG9wdGlvbmFsX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFNmaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0T3B0aW9uYWxTZml4ZWQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgb3B0aW9uYWxfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU2ZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsU2ZpeGVkNjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgb3B0aW9uYWxfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFNmaXhlZDY0LgogICAgICovCiAgICBsb25nIGdldE9wdGlvbmFsU2ZpeGVkNjQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IG9wdGlvbmFsX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEZsb2F0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEZsb2F0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IG9wdGlvbmFsX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxGbG9hdC4KICAgICAqLwogICAgZmxvYXQgZ2V0T3B0aW9uYWxGbG9hdCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIG9wdGlvbmFsX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxEb3VibGUgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsRG91YmxlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBvcHRpb25hbF9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbERvdWJsZS4KICAgICAqLwogICAgZG91YmxlIGdldE9wdGlvbmFsRG91YmxlKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBib29sIG9wdGlvbmFsX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQm9vbCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxCb29sKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgb3B0aW9uYWxfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQm9vbC4KICAgICAqLwogICAgYm9vbGVhbiBnZXRPcHRpb25hbEJvb2woKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbFN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTdHJpbmcuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T3B0aW9uYWxTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T3B0aW9uYWxTdHJpbmdCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsQnl0ZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEJ5dGVzLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T3B0aW9uYWxCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsZ3JvdXAgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsR3JvdXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbGdyb3VwLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgZ2V0T3B0aW9uYWxHcm91cCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbE5lc3RlZE1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsTmVzdGVkTWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTmVzdGVkTWVzc2FnZS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZU9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEZvcmVpZ25NZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW1wb3J0TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxJbXBvcnRNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEltcG9ydE1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbEltcG9ydE1lc3NhZ2VPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIG9wdGlvbmFsX25lc3RlZF9lbnVtID0gMjE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbE5lc3RlZEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsTmVzdGVkRW51bSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBvcHRpb25hbF9uZXN0ZWRfZW51bSA9IDIxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTmVzdGVkRW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGdldE9wdGlvbmFsTmVzdGVkRW51bSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9lbnVtID0gMjI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEZvcmVpZ25FbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEZvcmVpZ25FbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIG9wdGlvbmFsX2ZvcmVpZ25fZW51bSA9IDIyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRm9yZWlnbkVudW0uCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRPcHRpb25hbEZvcmVpZ25FbnVtKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIG9wdGlvbmFsX2ltcG9ydF9lbnVtID0gMjM7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEltcG9ydEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsSW1wb3J0RW51bSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIG9wdGlvbmFsX2ltcG9ydF9lbnVtID0gMjM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbXBvcnRFbnVtLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSBnZXRPcHRpb25hbEltcG9ydEVudW0oKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTdHJpbmdQaWVjZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxTdHJpbmdQaWVjZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nX3BpZWNlID0gMjQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFN0cmluZ1BpZWNlLgogICAgICovCiAgICBqYXZhLmxhbmcuU3RyaW5nIGdldE9wdGlvbmFsU3RyaW5nUGllY2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZ19waWVjZSA9IDI0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9wdGlvbmFsU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9wdGlvbmFsU3RyaW5nUGllY2VCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX2NvcmQgPSAyNSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxDb3JkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9jb3JkID0gMjUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxDb3JkLgogICAgICovCiAgICBqYXZhLmxhbmcuU3RyaW5nIGdldE9wdGlvbmFsQ29yZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbENvcmQuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9wdGlvbmFsQ29yZEJ5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIERlZmluZWQgaW4gdW5pdHRlc3RfaW1wb3J0X3B1YmxpYy5wcm90bwogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2UgPSAyNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxMYXp5TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxMYXp5TWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTGF6eU1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPcHRpb25hbExhenlNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZU9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF91bnZlcmlmaWVkX2xhenlfbWVzc2FnZSA9IDI4IFt1bnZlcmlmaWVkX2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZU9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFJlcGVhdGVkCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDMxOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRSZXBlYXRlZEludDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogUmVwZWF0ZWQKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMzE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbnQzMi4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkSW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogUmVwZWF0ZWQKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMzE7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkSW50MzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHJlcGVhdGVkX2ludDY0ID0gMzI7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbnQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFJlcGVhdGVkSW50NjRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHJlcGVhdGVkX2ludDY0ID0gMzI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbnQ2NC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkSW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCByZXBlYXRlZF9pbnQ2NCA9IDMyOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGxvbmcgZ2V0UmVwZWF0ZWRJbnQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHJlcGVhdGVkX3VpbnQzMiA9IDMzOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkVWludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UmVwZWF0ZWRVaW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiByZXBlYXRlZF91aW50MzIgPSAzMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFVpbnQzMi4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkVWludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHJlcGVhdGVkX3VpbnQzMiA9IDMzOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRVaW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRVaW50MzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCByZXBlYXRlZF91aW50NjQgPSAzNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFVpbnQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFJlcGVhdGVkVWludDY0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcmVwZWF0ZWRfdWludDY0ID0gMzQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRVaW50NjQuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFVpbnQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCByZXBlYXRlZF91aW50NjQgPSAzNDs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkVWludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgbG9uZyBnZXRSZXBlYXRlZFVpbnQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHJlcGVhdGVkX3NpbnQzMiA9IDM1OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU2ludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UmVwZWF0ZWRTaW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiByZXBlYXRlZF9zaW50MzIgPSAzNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFNpbnQzMi4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkU2ludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHJlcGVhdGVkX3NpbnQzMiA9IDM1OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTaW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRTaW50MzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCByZXBlYXRlZF9zaW50NjQgPSAzNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFNpbnQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFJlcGVhdGVkU2ludDY0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcmVwZWF0ZWRfc2ludDY0ID0gMzY7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTaW50NjQuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFNpbnQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCByZXBlYXRlZF9zaW50NjQgPSAzNjs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU2ludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgbG9uZyBnZXRSZXBlYXRlZFNpbnQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMzc7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRGaXhlZDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAzNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAzNzs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEZpeGVkMzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFJlcGVhdGVkRml4ZWQ2NExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCByZXBlYXRlZF9maXhlZDY0ID0gMzg7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGaXhlZDY0LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCByZXBlYXRlZF9maXhlZDY0ID0gMzg7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkNjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBsb25nIGdldFJlcGVhdGVkRml4ZWQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcmVwZWF0ZWRfc2ZpeGVkMzIgPSAzOTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFNmaXhlZDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UmVwZWF0ZWRTZml4ZWQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcmVwZWF0ZWRfc2ZpeGVkMzIgPSAzOTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFNmaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRTZml4ZWQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHJlcGVhdGVkX3NmaXhlZDMyID0gMzk7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFNmaXhlZDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkU2ZpeGVkMzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHJlcGVhdGVkX3NmaXhlZDY0ID0gNDA7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTZml4ZWQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFJlcGVhdGVkU2ZpeGVkNjRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHJlcGVhdGVkX3NmaXhlZDY0ID0gNDA7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTZml4ZWQ2NC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkU2ZpeGVkNjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCByZXBlYXRlZF9zZml4ZWQ2NCA9IDQwOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTZml4ZWQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGxvbmcgZ2V0UmVwZWF0ZWRTZml4ZWQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcmVwZWF0ZWRfZmxvYXQgPSA0MTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZsb2F0LgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRmxvYXQ+IGdldFJlcGVhdGVkRmxvYXRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHJlcGVhdGVkX2Zsb2F0ID0gNDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGbG9hdC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkRmxvYXRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCByZXBlYXRlZF9mbG9hdCA9IDQxOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGbG9hdCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGZsb2F0IGdldFJlcGVhdGVkRmxvYXQoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSByZXBlYXRlZF9kb3VibGUgPSA0Mjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZERvdWJsZS4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkRvdWJsZT4gZ2V0UmVwZWF0ZWREb3VibGVMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSByZXBlYXRlZF9kb3VibGUgPSA0Mjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZERvdWJsZS4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkRG91YmxlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHJlcGVhdGVkX2RvdWJsZSA9IDQyOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWREb3VibGUgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBkb3VibGUgZ2V0UmVwZWF0ZWREb3VibGUoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkQm9vbC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkJvb2xlYW4+IGdldFJlcGVhdGVkQm9vbExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCByZXBlYXRlZF9ib29sID0gNDM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRCb29sLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRCb29sQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCByZXBlYXRlZF9ib29sID0gNDM7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEJvb2wgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBib29sZWFuIGdldFJlcGVhdGVkQm9vbChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZyA9IDQ0OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU3RyaW5nLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgIGdldFJlcGVhdGVkU3RyaW5nTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nID0gNDQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTdHJpbmcuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFN0cmluZ0NvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU3RyaW5nIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRSZXBlYXRlZFN0cmluZyhpbnQgaW5kZXgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nID0gNDQ7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdmFsdWUgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkU3RyaW5nIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdCeXRlcyhpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEJ5dGVzLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IGdldFJlcGVhdGVkQnl0ZXNMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJ5dGVzIHJlcGVhdGVkX2J5dGVzID0gNDU7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRCeXRlcy4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkQnl0ZXNDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBieXRlcyByZXBlYXRlZF9ieXRlcyA9IDQ1OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRCeXRlcyBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRSZXBlYXRlZEJ5dGVzKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwPiAKICAgICAgICBnZXRSZXBlYXRlZEdyb3VwTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIGdldFJlcGVhdGVkR3JvdXAoaW50IGluZGV4KTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEdyb3VwQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXI+IAogICAgICAgIGdldFJlcGVhdGVkR3JvdXBPckJ1aWxkZXJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRHcm91cE9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gCiAgICAgICAgZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZShpbnQgaW5kZXgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKAogICAgICAgIGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4gCiAgICAgICAgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZShpbnQgaW5kZXgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlT3JCdWlsZGVyKAogICAgICAgIGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZT4gCiAgICAgICAgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoaW50IGluZGV4KTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWROZXN0ZWRFbnVtLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+IGdldFJlcGVhdGVkTmVzdGVkRW51bUxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVwZWF0ZWRfbmVzdGVkX2VudW0gPSA1MTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZE5lc3RlZEVudW0uCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZE5lc3RlZEVudW1Db3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWROZXN0ZWRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGdldFJlcGVhdGVkTmVzdGVkRW51bShpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9lbnVtID0gNTI7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRGb3JlaWduRW51bS4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPiBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZvcmVpZ25FbnVtLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRGb3JlaWduRW51bUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHJlcGVhdGVkX2ZvcmVpZ25fZW51bSA9IDUyOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGb3JlaWduRW51bSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbXBvcnRFbnVtLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4gZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbXBvcnRFbnVtLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSByZXBlYXRlZF9pbXBvcnRfZW51bSA9IDUzOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbXBvcnRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFN0cmluZ1BpZWNlLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgIGdldFJlcGVhdGVkU3RyaW5nUGllY2VMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHZhbHVlIHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUJ5dGVzKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkQ29yZC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLlN0cmluZz4KICAgICAgICBnZXRSZXBlYXRlZENvcmRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRDb3JkLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRDb3JkQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX2NvcmQgPSA1NSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkQ29yZCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0UmVwZWF0ZWRDb3JkKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdmFsdWUgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkQ29yZCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldFJlcGVhdGVkQ29yZEJ5dGVzKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiAKICAgICAgICBnZXRSZXBlYXRlZExhenlNZXNzYWdlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2UoaW50IGluZGV4KTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZExhenlNZXNzYWdlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZU9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFNpbmd1bGFyIHdpdGggZGVmYXVsdHMKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlZmF1bHRfaW50MzIgPSA2MSBbZGVmYXVsdCA9IDQxXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdEludDMyKCk7CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBTaW5ndWxhciB3aXRoIGRlZmF1bHRzCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWZhdWx0X2ludDMyID0gNjEgW2RlZmF1bHQgPSA0MV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdEludDMyLgogICAgICovCiAgICBpbnQgZ2V0RGVmYXVsdEludDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBkZWZhdWx0X2ludDY0ID0gNjIgW2RlZmF1bHQgPSA0Ml07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0SW50NjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRJbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBkZWZhdWx0X2ludDY0ID0gNjIgW2RlZmF1bHQgPSA0Ml07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdEludDY0LgogICAgICovCiAgICBsb25nIGdldERlZmF1bHRJbnQ2NCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIGRlZmF1bHRfdWludDMyID0gNjMgW2RlZmF1bHQgPSA0M107PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0VWludDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0VWludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBkZWZhdWx0X3VpbnQzMiA9IDYzIFtkZWZhdWx0ID0gNDNdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRVaW50MzIuCiAgICAgKi8KICAgIGludCBnZXREZWZhdWx0VWludDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50NjQgZGVmYXVsdF91aW50NjQgPSA2NCBbZGVmYXVsdCA9IDQ0XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRVaW50NjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRVaW50NjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IGRlZmF1bHRfdWludDY0ID0gNjQgW2RlZmF1bHQgPSA0NF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdFVpbnQ2NC4KICAgICAqLwogICAgbG9uZyBnZXREZWZhdWx0VWludDY0KCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgZGVmYXVsdF9zaW50MzIgPSA2NSBbZGVmYXVsdCA9IC00NV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U2ludDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0U2ludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQzMiBkZWZhdWx0X3NpbnQzMiA9IDY1IFtkZWZhdWx0ID0gLTQ1XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U2ludDMyLgogICAgICovCiAgICBpbnQgZ2V0RGVmYXVsdFNpbnQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IGRlZmF1bHRfc2ludDY0ID0gNjYgW2RlZmF1bHQgPSA0Nl07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U2ludDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0U2ludDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBkZWZhdWx0X3NpbnQ2NCA9IDY2IFtkZWZhdWx0ID0gNDZdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTaW50NjQuCiAgICAgKi8KICAgIGxvbmcgZ2V0RGVmYXVsdFNpbnQ2NCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBkZWZhdWx0X2ZpeGVkMzIgPSA2NyBbZGVmYXVsdCA9IDQ3XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRGaXhlZDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0Rml4ZWQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIGRlZmF1bHRfZml4ZWQzMiA9IDY3IFtkZWZhdWx0ID0gNDddOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0RGVmYXVsdEZpeGVkMzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgZGVmYXVsdF9maXhlZDY0ID0gNjggW2RlZmF1bHQgPSA0OF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Rml4ZWQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdEZpeGVkNjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQ2NCBkZWZhdWx0X2ZpeGVkNjQgPSA2OCBbZGVmYXVsdCA9IDQ4XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Rml4ZWQ2NC4KICAgICAqLwogICAgbG9uZyBnZXREZWZhdWx0Rml4ZWQ2NCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgZGVmYXVsdF9zZml4ZWQzMiA9IDY5IFtkZWZhdWx0ID0gNDldOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFNmaXhlZDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0U2ZpeGVkMzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgZGVmYXVsdF9zZml4ZWQzMiA9IDY5IFtkZWZhdWx0ID0gNDldOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTZml4ZWQzMi4KICAgICAqLwogICAgaW50IGdldERlZmF1bHRTZml4ZWQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgZGVmYXVsdF9zZml4ZWQ2NCA9IDcwIFtkZWZhdWx0ID0gLTUwXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTZml4ZWQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdFNmaXhlZDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IGRlZmF1bHRfc2ZpeGVkNjQgPSA3MCBbZGVmYXVsdCA9IC01MF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdFNmaXhlZDY0LgogICAgICovCiAgICBsb25nIGdldERlZmF1bHRTZml4ZWQ2NCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgZGVmYXVsdF9mbG9hdCA9IDcxIFtkZWZhdWx0ID0gNTEuNV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0RmxvYXQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRGbG9hdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmbG9hdCBkZWZhdWx0X2Zsb2F0ID0gNzEgW2RlZmF1bHQgPSA1MS41XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0RmxvYXQuCiAgICAgKi8KICAgIGZsb2F0IGdldERlZmF1bHRGbG9hdCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIGRlZmF1bHRfZG91YmxlID0gNzIgW2RlZmF1bHQgPSA1MjAwMF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0RG91YmxlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0RG91YmxlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBkZWZhdWx0X2RvdWJsZSA9IDcyIFtkZWZhdWx0ID0gNTIwMDBdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHREb3VibGUuCiAgICAgKi8KICAgIGRvdWJsZSBnZXREZWZhdWx0RG91YmxlKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBib29sIGRlZmF1bHRfYm9vbCA9IDczIFtkZWZhdWx0ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Qm9vbCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdEJvb2woKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBkZWZhdWx0X2Jvb2wgPSA3MyBbZGVmYXVsdCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRCb29sLgogICAgICovCiAgICBib29sZWFuIGdldERlZmF1bHRCb29sKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmcgPSA3NCBbZGVmYXVsdCA9ICJoZWxsbyJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFN0cmluZyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdFN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmcgPSA3NCBbZGVmYXVsdCA9ICJoZWxsbyJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTdHJpbmcuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdFN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmcgPSA3NCBbZGVmYXVsdCA9ICJoZWxsbyJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBkZWZhdWx0U3RyaW5nLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZWZhdWx0U3RyaW5nQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIGRlZmF1bHRfYnl0ZXMgPSA3NSBbZGVmYXVsdCA9ICJ3b3JsZCJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0Qnl0ZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgZGVmYXVsdF9ieXRlcyA9IDc1IFtkZWZhdWx0ID0gIndvcmxkIl07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdEJ5dGVzLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0RGVmYXVsdEJ5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBkZWZhdWx0X25lc3RlZF9lbnVtID0gODEgW2RlZmF1bHQgPSBCQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdE5lc3RlZEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHROZXN0ZWRFbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGRlZmF1bHRfbmVzdGVkX2VudW0gPSA4MSBbZGVmYXVsdCA9IEJBUl07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdE5lc3RlZEVudW0uCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBnZXREZWZhdWx0TmVzdGVkRW51bSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZvcmVpZ25FbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0Rm9yZWlnbkVudW0oKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGb3JlaWduRW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldERlZmF1bHRGb3JlaWduRW51bSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBkZWZhdWx0X2ltcG9ydF9lbnVtID0gODMgW2RlZmF1bHQgPSBJTVBPUlRfTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEltcG9ydEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRJbXBvcnRFbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgZGVmYXVsdF9pbXBvcnRfZW51bSA9IDgzIFtkZWZhdWx0ID0gSU1QT1JUX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0SW1wb3J0RW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0RGVmYXVsdEltcG9ydEVudW0oKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTdHJpbmdQaWVjZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdFN0cmluZ1BpZWNlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U3RyaW5nUGllY2UuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdFN0cmluZ1BpZWNlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVmYXVsdFN0cmluZ1BpZWNlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZWZhdWx0U3RyaW5nUGllY2VCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Q29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdENvcmQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdENvcmQuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdENvcmQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlZmF1bHRDb3JkLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZWZhdWx0Q29yZEJ5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gMTExOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mVWludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSAxMTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZVaW50MzIuCiAgICAgKi8KICAgIGludCBnZXRPbmVvZlVpbnQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZk5lc3RlZE1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mTmVzdGVkTWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZk5lc3RlZE1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPbmVvZk5lc3RlZE1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mU3RyaW5nKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAxMTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9uZW9mU3RyaW5nQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gMTE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZCeXRlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDExNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZMYXp5TmVzdGVkTWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9sYXp5X25lc3RlZF9tZXNzYWdlID0gMTE1IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZk5lc3RlZE1lc3NhZ2UyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZk5lc3RlZE1lc3NhZ2UyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZOZXN0ZWRNZXNzYWdlMi4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBnZXRPbmVvZk5lc3RlZE1lc3NhZ2UyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyIGdldE9uZW9mTmVzdGVkTWVzc2FnZTJPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBUZXN0cyB0b1N0cmluZyBmb3Igbm9uLXJlcGVhdGVkIGZpZWxkcyB3aXRoIGEgbGlzdCBzdWZmaXgKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlY2VwdGl2ZWx5X25hbWVkX2xpc3QgPSAxMTY7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVjZXB0aXZlbHlOYW1lZExpc3QoKTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRlc3RzIHRvU3RyaW5nIGZvciBub24tcmVwZWF0ZWQgZmllbGRzIHdpdGggYSBsaXN0IHN1ZmZpeAogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVjZXB0aXZlbHlfbmFtZWRfbGlzdCA9IDExNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdC4KICAgICAqLwogICAgaW50IGdldERlY2VwdGl2ZWx5TmFtZWRMaXN0KCk7CgogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PbmVvZkZpZWxkQ2FzZSBnZXRPbmVvZkZpZWxkQ2FzZSgpOwogIH0KICAvKioKICAgKiA8cHJlPgogICAqIFNhbWUgYXMgVGVzdEFsbFR5cGVzIGJ1dCB3aXRoIHRoZSBsaXRlIHJ1bnRpbWUuCiAgICogPC9wcmU+CiAgICoKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RBbGxUeXBlc0xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUpCiAgICAgIFRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RBbGxUeXBlc0xpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdEFsbFR5cGVzTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RBbGxUeXBlc0xpdGUoKSB7CiAgICAgIG9wdGlvbmFsU3RyaW5nXyA9ICIiOwogICAgICBvcHRpb25hbEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgb3B0aW9uYWxOZXN0ZWRFbnVtXyA9IDE7CiAgICAgIG9wdGlvbmFsRm9yZWlnbkVudW1fID0gNDsKICAgICAgb3B0aW9uYWxJbXBvcnRFbnVtXyA9IDc7CiAgICAgIG9wdGlvbmFsU3RyaW5nUGllY2VfID0gIiI7CiAgICAgIG9wdGlvbmFsQ29yZF8gPSAiIjsKICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcmVwZWF0ZWRJbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHJlcGVhdGVkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICByZXBlYXRlZFVpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHJlcGVhdGVkU2ludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICByZXBlYXRlZFNpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcmVwZWF0ZWRGaXhlZDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgcmVwZWF0ZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcmVwZWF0ZWRTZml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHJlcGVhdGVkRmxvYXRfID0gZW1wdHlGbG9hdExpc3QoKTsKICAgICAgcmVwZWF0ZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgIHJlcGVhdGVkQm9vbF8gPSBlbXB0eUJvb2xlYW5MaXN0KCk7CiAgICAgIHJlcGVhdGVkU3RyaW5nXyA9CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkQnl0ZXNfID0gZW1wdHlMaXN0KGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jbGFzcyk7CiAgICAgIHJlcGVhdGVkR3JvdXBfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcmVwZWF0ZWROZXN0ZWRFbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkSW1wb3J0RW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfID0KICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdC5lbXB0eUxpc3QoKTsKICAgICAgcmVwZWF0ZWRDb3JkXyA9CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICBkZWZhdWx0SW50MzJfID0gNDE7CiAgICAgIGRlZmF1bHRJbnQ2NF8gPSA0Mkw7CiAgICAgIGRlZmF1bHRVaW50MzJfID0gNDM7CiAgICAgIGRlZmF1bHRVaW50NjRfID0gNDRMOwogICAgICBkZWZhdWx0U2ludDMyXyA9IC00NTsKICAgICAgZGVmYXVsdFNpbnQ2NF8gPSA0Nkw7CiAgICAgIGRlZmF1bHRGaXhlZDMyXyA9IDQ3OwogICAgICBkZWZhdWx0Rml4ZWQ2NF8gPSA0OEw7CiAgICAgIGRlZmF1bHRTZml4ZWQzMl8gPSA0OTsKICAgICAgZGVmYXVsdFNmaXhlZDY0XyA9IC01MEw7CiAgICAgIGRlZmF1bHRGbG9hdF8gPSA1MS41RjsKICAgICAgZGVmYXVsdERvdWJsZV8gPSA1MjAwMEQ7CiAgICAgIGRlZmF1bHRCb29sXyA9IHRydWU7CiAgICAgIGRlZmF1bHRTdHJpbmdfID0gImhlbGxvIjsKICAgICAgZGVmYXVsdEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoIndvcmxkIik7CiAgICAgIGRlZmF1bHROZXN0ZWRFbnVtXyA9IDI7CiAgICAgIGRlZmF1bHRGb3JlaWduRW51bV8gPSA1OwogICAgICBkZWZhdWx0SW1wb3J0RW51bV8gPSA4OwogICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gImFiYyI7CiAgICAgIGRlZmF1bHRDb3JkXyA9ICIxMjMiOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RBbGxUeXBlc0xpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIC8qKgogICAgICogUHJvdG9idWYgZW51bSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bX0KICAgICAqLwogICAgcHVibGljIGVudW0gTmVzdGVkRW51bQogICAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Qcm90b2NvbE1lc3NhZ2VFbnVtIHsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkZPTyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgRk9PKDEpLAogICAgICAvKioKICAgICAgICogPGNvZGU+QkFSID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBCQVIoMiksCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5CQVogPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIEJBWigzKSwKICAgICAgOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkZPTyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRk9PX1ZBTFVFID0gMTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkJBUiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgQkFSX1ZBTFVFID0gMjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkJBWiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgQkFaX1ZBTFVFID0gMzsKCgogICAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgc3RhdGljIE5lc3RlZEVudW0gdmFsdWVPZihpbnQgdmFsdWUpIHsKICAgICAgICByZXR1cm4gZm9yTnVtYmVyKHZhbHVlKTsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIE5lc3RlZEVudW0gZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICAgIGNhc2UgMTogcmV0dXJuIEZPTzsKICAgICAgICAgIGNhc2UgMjogcmV0dXJuIEJBUjsKICAgICAgICAgIGNhc2UgMzogcmV0dXJuIEJBWjsKICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPE5lc3RlZEVudW0+CiAgICAgICAgICBpbnRlcm5hbEdldFZhbHVlTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbFZhbHVlTWFwOwogICAgICB9CiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8CiAgICAgICAgICBOZXN0ZWRFbnVtPiBpbnRlcm5hbFZhbHVlTWFwID0KICAgICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8TmVzdGVkRW51bT4oKSB7CiAgICAgICAgICAgICAgcHVibGljIE5lc3RlZEVudW0gZmluZFZhbHVlQnlOdW1iZXIoaW50IG51bWJlcikgewogICAgICAgICAgICAgICAgcmV0dXJuIE5lc3RlZEVudW0uZm9yTnVtYmVyKG51bWJlcik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9OwoKICAgICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvcgogICAgICAgICAgZ2V0VmFsdWVEZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCkuZ2V0VmFsdWVzKCkuZ2V0KG9yZGluYWwoKSk7CiAgICAgIH0KICAgICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMCk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIE5lc3RlZEVudW1bXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICAgIHB1YmxpYyBzdGF0aWMgTmVzdGVkRW51bSB2YWx1ZU9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yIGRlc2MpIHsKICAgICAgICBpZiAoZGVzYy5nZXRUeXBlKCkgIT0gZ2V0RGVzY3JpcHRvcigpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigKICAgICAgICAgICAgIkVudW1WYWx1ZURlc2NyaXB0b3IgaXMgbm90IGZvciB0aGlzIHR5cGUuIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBWQUxVRVNbZGVzYy5nZXRJbmRleCgpXTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CgogICAgICBwcml2YXRlIE5lc3RlZEVudW0oaW50IHZhbHVlKSB7CiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgICB9CgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtKQogICAgfQoKICAgIHB1YmxpYyBpbnRlcmZhY2UgTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBiYiA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGJiIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIGJvb2xlYW4gaGFzQmIoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGJiID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJiLgogICAgICAgKi8KICAgICAgaW50IGdldEJiKCk7CgogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgY2MgPSAyOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBjYyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBib29sZWFuIGhhc0NjKCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBjYyA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjYy4KICAgICAgICovCiAgICAgIGxvbmcgZ2V0Q2MoKTsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgZGQuCiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0RGRMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgZGQuCiAgICAgICAqLwogICAgICBpbnQgZ2V0RGRDb3VudCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgZGQgPSAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBkZCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBpbnQgZ2V0RGQoaW50IGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBOZXN0ZWRNZXNzYWdlIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKQogICAgICAgIE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAgIC8vIFVzZSBOZXN0ZWRNZXNzYWdlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgIHByaXZhdGUgTmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgfQogICAgICBwcml2YXRlIE5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgZGRfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICAgIHJldHVybiBuZXcgTmVzdGVkTWVzc2FnZSgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2VfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2VfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEJCX0ZJRUxEX05VTUJFUiA9IDE7CiAgICAgIHByaXZhdGUgaW50IGJiXyA9IDA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBiYiA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGJiIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzQmIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBiYiA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBiYi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRCYigpIHsKICAgICAgICByZXR1cm4gYmJfOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBDQ19GSUVMRF9OVU1CRVIgPSAyOwogICAgICBwcml2YXRlIGxvbmcgY2NfID0gMEw7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBjYyA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGNjIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzQ2MoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBjYyA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjYy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0Q2MoKSB7CiAgICAgICAgcmV0dXJuIGNjXzsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRERfRklFTERfTlVNQkVSID0gMzsKICAgICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IGRkXyA9CiAgICAgICAgICBlbXB0eUludExpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBkZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0RGRMaXN0KCkgewogICAgICAgIHJldHVybiBkZF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBkZC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0RGRDb3VudCgpIHsKICAgICAgICByZXR1cm4gZGRfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgZGQgPSAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBkZCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldERkKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBkZF8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICBwcml2YXRlIGludCBkZE1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGJiXyk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgb3V0cHV0LndyaXRlSW50NjQoMiwgY2NfKTsKICAgICAgICB9CiAgICAgICAgaWYgKGdldERkTGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDI2KTsKICAgICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKGRkTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZGRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVJbnQzMk5vVGFnKGRkXy5nZXRJbnQoaSkpOwogICAgICAgIH0KICAgICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgICBzaXplID0gMDsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBiYl8pOwogICAgICAgIH0KICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDY0U2l6ZSgyLCBjY18pOwogICAgICAgIH0KICAgICAgICB7CiAgICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBkZF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGRfLmdldEludChpKSk7CiAgICAgICAgICB9CiAgICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgICAgaWYgKCFnZXREZExpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgc2l6ZSArPSAxOwogICAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgICAgfQogICAgICAgICAgZGRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgICByZXR1cm4gc2l6ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgICB9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb2JqOwoKICAgICAgICBpZiAoaGFzQmIoKSAhPSBvdGhlci5oYXNCYigpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKGhhc0JiKCkpIHsKICAgICAgICAgIGlmIChnZXRCYigpCiAgICAgICAgICAgICAgIT0gb3RoZXIuZ2V0QmIoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAoaGFzQ2MoKSAhPSBvdGhlci5oYXNDYygpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKGhhc0NjKCkpIHsKICAgICAgICAgIGlmIChnZXRDYygpCiAgICAgICAgICAgICAgIT0gb3RoZXIuZ2V0Q2MoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAoIWdldERkTGlzdCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RGRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICAgIH0KICAgICAgICBpbnQgaGFzaCA9IDQxOwogICAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICAgIGlmIChoYXNCYigpKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBCQl9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRCYigpOwogICAgICAgIH0KICAgICAgICBpZiAoaGFzQ2MoKSkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgQ0NfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgICBnZXRDYygpKTsKICAgICAgICB9CiAgICAgICAgaWYgKGdldERkQ291bnQoKSA+IDApIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEREX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERkTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgICAgfQogICAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICAgIHJldHVybiBoYXNoOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwcm90b3R5cGUpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICAgIHJldHVybiBidWlsZGVyOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIHsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLm5ld0J1aWxkZXIoKQogICAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgICAgYmJfID0gMDsKICAgICAgICAgIGNjXyA9IDBMOwogICAgICAgICAgZGRfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGJ1aWxkKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UodGhpcyk7CiAgICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgICAgb25CdWlsdCgpOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXN1bHQpIHsKICAgICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgcmVzdWx0LmJiXyA9IGJiXzsKICAgICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgICAgcmVzdWx0LmNjXyA9IGNjXzsKICAgICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgICAgZGRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgcmVzdWx0LmRkXyA9IGRkXzsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIHsKICAgICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKW90aGVyKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgICBpZiAob3RoZXIuaGFzQmIoKSkgewogICAgICAgICAgICBzZXRCYihvdGhlci5nZXRCYigpKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChvdGhlci5oYXNDYygpKSB7CiAgICAgICAgICAgIHNldENjKG90aGVyLmdldENjKCkpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFvdGhlci5kZF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChkZF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgZGRfID0gb3RoZXIuZGRfOwogICAgICAgICAgICAgIGRkXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGVuc3VyZURkSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgZGRfLmFkZEFsbChvdGhlci5kZF8pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICAgIGJiXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDgKICAgICAgICAgICAgICAgIGNhc2UgMTY6IHsKICAgICAgICAgICAgICAgICAgY2NfID0gaW5wdXQucmVhZEludDY0KCk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYKICAgICAgICAgICAgICAgIGNhc2UgMjQ6IHsKICAgICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgICAgZW5zdXJlRGRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgZGRfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgMjQKICAgICAgICAgICAgICAgIGNhc2UgMjY6IHsKICAgICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgICAgZW5zdXJlRGRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICAgIGRkXy5hZGRJbnQoaW5wdXQucmVhZEludDMyKCkpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgMjYKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgIHByaXZhdGUgaW50IGJiXyA7CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYmIgPSAxOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGJiIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzQmIoKSB7CiAgICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGJiID0gMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgYmIuCiAgICAgICAgICovCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgZ2V0QmIoKSB7CiAgICAgICAgICByZXR1cm4gYmJfOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBiYiA9IDE7PC9jb2RlPgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYmIgdG8gc2V0LgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRCYihpbnQgdmFsdWUpIHsKCiAgICAgICAgICBiYl8gPSB2YWx1ZTsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGJiID0gMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQmIoKSB7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgICBiYl8gPSAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgbG9uZyBjY18gOwogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGNjID0gMjs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBjYyBmaWVsZCBpcyBzZXQuCiAgICAgICAgICovCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBib29sZWFuIGhhc0NjKCkgewogICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBjYyA9IDI7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhlIGNjLgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgbG9uZyBnZXRDYygpIHsKICAgICAgICAgIHJldHVybiBjY187CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGNjID0gMjs8L2NvZGU+CiAgICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBjYyB0byBzZXQuCiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldENjKGxvbmcgdmFsdWUpIHsKCiAgICAgICAgICBjY18gPSB2YWx1ZTsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGNjID0gMjs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQ2MoKSB7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgICBjY18gPSAwTDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCBkZF8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBwcml2YXRlIHZvaWQgZW5zdXJlRGRJc011dGFibGUoKSB7CiAgICAgICAgICBpZiAoIWRkXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgICBkZF8gPSBtYWtlTXV0YWJsZUNvcHkoZGRfKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgZGQgPSAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgZGQuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICBnZXREZExpc3QoKSB7CiAgICAgICAgICBkZF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmV0dXJuIGRkXzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgZGQgPSAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgZGQuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGludCBnZXREZENvdW50KCkgewogICAgICAgICAgcmV0dXJuIGRkXy5zaXplKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgICAqIEByZXR1cm4gVGhlIGRkIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgaW50IGdldERkKGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGRkXy5nZXRJbnQoaW5kZXgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZCB0byBzZXQuCiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERkKAogICAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICAgIGVuc3VyZURkSXNNdXRhYmxlKCk7CiAgICAgICAgICBkZF8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRkIHRvIGFkZC4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRGQoaW50IHZhbHVlKSB7CgogICAgICAgICAgZW5zdXJlRGRJc011dGFibGUoKTsKICAgICAgICAgIGRkXy5hZGRJbnQodmFsdWUpOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgZGQgPSAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgZGQgdG8gYWRkLgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxEZCgKICAgICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgICBlbnN1cmVEZElzTXV0YWJsZSgpOwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgIHZhbHVlcywgZGRfKTsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRkKCkgewogICAgICAgICAgZGRfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCgogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpCiAgICAgIH0KCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgREVGQVVMVF9JTlNUQU5DRTsKICAgICAgc3RhdGljIHsKICAgICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE5lc3RlZE1lc3NhZ2U+CiAgICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxOZXN0ZWRNZXNzYWdlPigpIHsKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIE5lc3RlZE1lc3NhZ2UgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOZXN0ZWRNZXNzYWdlPiBwYXJzZXIoKSB7CiAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8TmVzdGVkTWVzc2FnZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgIH0KCiAgICBwdWJsaWMgaW50ZXJmYWNlIE5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZCA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRkIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIGJvb2xlYW4gaGFzRGQoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRkLgogICAgICAgKi8KICAgICAgaW50IGdldERkKCk7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIE5lc3RlZE1lc3NhZ2UyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikKICAgICAgICBOZXN0ZWRNZXNzYWdlMk9yQnVpbGRlciB7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgICAgLy8gVXNlIE5lc3RlZE1lc3NhZ2UyLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgIHByaXZhdGUgTmVzdGVkTWVzc2FnZTIoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBOZXN0ZWRNZXNzYWdlMigpIHsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgICAgcmV0dXJuIG5ldyBOZXN0ZWRNZXNzYWdlMigpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2UyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERF9GSUVMRF9OVU1CRVIgPSAxOwogICAgICBwcml2YXRlIGludCBkZF8gPSAwOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RkKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RGQoKSB7CiAgICAgICAgcmV0dXJuIGRkXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGRkXyk7CiAgICAgICAgfQogICAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICAgIHNpemUgPSAwOwogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDEsIGRkXyk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgICByZXR1cm4gc2l6ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgICAgfQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikgb2JqOwoKICAgICAgICBpZiAoaGFzRGQoKSAhPSBvdGhlci5oYXNEZCgpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKGhhc0RkKCkpIHsKICAgICAgICAgIGlmIChnZXREZCgpCiAgICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGQoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgICAgfQogICAgICAgIGludCBoYXNoID0gNDE7CiAgICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgICAgaWYgKGhhc0RkKCkpIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEREX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERkKCk7CiAgICAgICAgfQogICAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICAgIHJldHVybiBoYXNoOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbSgKICAgICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcHJvdG90eXBlKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTJ9CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMk9yQnVpbGRlciB7CiAgICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZTJfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5CdWlsZGVyLmNsYXNzKTsKICAgICAgICB9CgogICAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLm5ld0J1aWxkZXIoKQogICAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgICAgZGRfID0gMDsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2UyX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIGJ1aWxkKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKHRoaXMpOwogICAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICAgIG9uQnVpbHQoKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHJlc3VsdCkgewogICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICByZXN1bHQuZGRfID0gZGRfOwogICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikgewogICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKW90aGVyKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICAgIGlmIChvdGhlci5oYXNEZCgpKSB7CiAgICAgICAgICAgIHNldERkKG90aGVyLmdldERkKCkpOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICAgIGRkXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDgKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgIHByaXZhdGUgaW50IGRkXyA7CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGQgPSAxOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRkIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGQoKSB7CiAgICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRkID0gMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgZGQuCiAgICAgICAgICovCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgZ2V0RGQoKSB7CiAgICAgICAgICByZXR1cm4gZGRfOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZCA9IDE7PC9jb2RlPgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGQgdG8gc2V0LgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXREZChpbnQgdmFsdWUpIHsKCiAgICAgICAgICBkZF8gPSB2YWx1ZTsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRkID0gMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGQoKSB7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgICBkZF8gPSAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgoKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikKICAgICAgfQoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIHN0YXRpYyB7CiAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE5lc3RlZE1lc3NhZ2UyPgogICAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8TmVzdGVkTWVzc2FnZTI+KCkgewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgTmVzdGVkTWVzc2FnZTIgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOZXN0ZWRNZXNzYWdlMj4gcGFyc2VyKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE5lc3RlZE1lc3NhZ2UyPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgIH0KCiAgICBwdWJsaWMgaW50ZXJmYWNlIE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIGJvb2xlYW4gaGFzQSgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYS4KICAgICAgICovCiAgICAgIGludCBnZXRBKCk7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXB9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgT3B0aW9uYWxHcm91cCBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgICBPcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgICAvLyBVc2UgT3B0aW9uYWxHcm91cC5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgICBwcml2YXRlIE9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBPcHRpb25hbEdyb3VwKCkgewogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICByZXR1cm4gbmV3IE9wdGlvbmFsR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9PcHRpb25hbEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBBX0ZJRUxEX05VTUJFUiA9IDE3OwogICAgICBwcml2YXRlIGludCBhXyA9IDA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRBKCkgewogICAgICAgIHJldHVybiBhXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIG91dHB1dC53cml0ZUludDMyKDE3LCBhXyk7CiAgICAgICAgfQogICAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICAgIHNpemUgPSAwOwogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDE3LCBhXyk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgICByZXR1cm4gc2l6ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCkpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgICB9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCkgb2JqOwoKICAgICAgICBpZiAoaGFzQSgpICE9IG90aGVyLmhhc0EoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICAgIGlmIChnZXRBKCkKICAgICAgICAgICAgICAhPSBvdGhlci5nZXRBKCkpIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICAgIH0KICAgICAgICBpbnQgaGFzaCA9IDQxOwogICAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEFfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0QSgpOwogICAgICAgIH0KICAgICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgICByZXR1cm4gaGFzaDsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcHJvdG90eXBlKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cH0KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlciB7CiAgICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX09wdGlvbmFsR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgIH0KCiAgICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5uZXdCdWlsZGVyKCkKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgIGFfID0gMDsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgYnVpbGQoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCh0aGlzKTsKICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHJlc3VsdCkgewogICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICByZXN1bHQuYV8gPSBhXzsKICAgICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCkgewogICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXApb3RoZXIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICAgIGlmIChvdGhlci5oYXNBKCkpIHsKICAgICAgICAgICAgc2V0QShvdGhlci5nZXRBKCkpOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAxMzY6IHsKICAgICAgICAgICAgICAgICAgYV8gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxMzYKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgIHByaXZhdGUgaW50IGFfIDsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgICAgICovCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBib29sZWFuIGhhc0EoKSB7CiAgICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgYS4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGludCBnZXRBKCkgewogICAgICAgICAgcmV0dXJuIGFfOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYSB0byBzZXQuCiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEEoaW50IHZhbHVlKSB7CgogICAgICAgICAgYV8gPSB2YWx1ZTsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQSgpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgIGFfID0gMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgfQoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBERUZBVUxUX0lOU1RBTkNFOwogICAgICBzdGF0aWMgewogICAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cD4KICAgICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPE9wdGlvbmFsR3JvdXA+KCkgewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgT3B0aW9uYWxHcm91cCBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE9wdGlvbmFsR3JvdXA+IHBhcnNlcigpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxPcHRpb25hbEdyb3VwPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICB9CgogICAgfQoKICAgIHB1YmxpYyBpbnRlcmZhY2UgUmVwZWF0ZWRHcm91cE9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXApCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgYm9vbGVhbiBoYXNBKCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICAgKi8KICAgICAgaW50IGdldEEoKTsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cH0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBSZXBlYXRlZEdyb3VwIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKQogICAgICAgIFJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAgIC8vIFVzZSBSZXBlYXRlZEdyb3VwLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgIHByaXZhdGUgUmVwZWF0ZWRHcm91cChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgfQogICAgICBwcml2YXRlIFJlcGVhdGVkR3JvdXAoKSB7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICAgIHJldHVybiBuZXcgUmVwZWF0ZWRHcm91cCgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX1JlcGVhdGVkR3JvdXBfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX1JlcGVhdGVkR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEFfRklFTERfTlVNQkVSID0gNDc7CiAgICAgIHByaXZhdGUgaW50IGFfID0gMDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0EoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgICAgcmV0dXJuIGFfOwogICAgICB9CgogICAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoNDcsIGFfKTsKICAgICAgICB9CiAgICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgICAgc2l6ZSA9IDA7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoNDcsIGFfKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICAgIHJldHVybiBzaXplOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICAgIH0KICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKSBvYmo7CgogICAgICAgIGlmIChoYXNBKCkgIT0gb3RoZXIuaGFzQSgpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKGhhc0EoKSkgewogICAgICAgICAgaWYgKGdldEEoKQogICAgICAgICAgICAgICE9IG90aGVyLmdldEEoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgICAgfQogICAgICAgIGludCBoYXNoID0gNDE7CiAgICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgICAgaWYgKGhhc0EoKSkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgQV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRBKCk7CiAgICAgICAgfQogICAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICAgIHJldHVybiBoYXNoOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwcm90b3R5cGUpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICAgIHJldHVybiBidWlsZGVyOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyIHsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfUmVwZWF0ZWRHcm91cF9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLm5ld0J1aWxkZXIoKQogICAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgICAgYV8gPSAwOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfUmVwZWF0ZWRHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBidWlsZCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKHRoaXMpOwogICAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICAgIG9uQnVpbHQoKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgcmVzdWx0KSB7CiAgICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICAgIHJlc3VsdC5hXyA9IGFfOwogICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKSB7CiAgICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cClvdGhlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgICAgaWYgKG90aGVyLmhhc0EoKSkgewogICAgICAgICAgICBzZXRBKG90aGVyLmdldEEoKSk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDM3NjogewogICAgICAgICAgICAgICAgICBhXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDM3NgogICAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgICAgcHJpdmF0ZSBpbnQgYV8gOwogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzQSgpIHsKICAgICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgICAgICByZXR1cm4gYV87CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBhIHRvIHNldC4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0QShpbnQgdmFsdWUpIHsKCiAgICAgICAgICBhXyA9IHZhbHVlOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJBKCkgewogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgYV8gPSAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgoKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKQogICAgICB9CgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIHN0YXRpYyB7CiAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEdyb3VwPgogICAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UmVwZWF0ZWRHcm91cD4oKSB7CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBSZXBlYXRlZEdyb3VwIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UmVwZWF0ZWRHcm91cD4gcGFyc2VyKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlcGVhdGVkR3JvdXA+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMV87CiAgICBwcml2YXRlIGludCBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3Qgb25lb2ZGaWVsZF87CiAgICBwdWJsaWMgZW51bSBPbmVvZkZpZWxkQ2FzZQogICAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2UuSW50ZXJuYWxPbmVPZkVudW0gewogICAgICBPTkVPRl9VSU5UMzIoMTExKSwKICAgICAgT05FT0ZfTkVTVEVEX01FU1NBR0UoMTEyKSwKICAgICAgT05FT0ZfU1RSSU5HKDExMyksCiAgICAgIE9ORU9GX0JZVEVTKDExNCksCiAgICAgIE9ORU9GX0xBWllfTkVTVEVEX01FU1NBR0UoMTE1KSwKICAgICAgT05FT0ZfTkVTVEVEX01FU1NBR0UyKDExNyksCiAgICAgIE9ORU9GRklFTERfTk9UX1NFVCgwKTsKICAgICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CiAgICAgIHByaXZhdGUgT25lb2ZGaWVsZENhc2UoaW50IHZhbHVlKSB7CiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWJlciBvZiB0aGUgZW51bSB0byBsb29rIGZvci4KICAgICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWJlci4KICAgICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjZm9yTnVtYmVyKGludCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIHN0YXRpYyBPbmVvZkZpZWxkQ2FzZSB2YWx1ZU9mKGludCB2YWx1ZSkgewogICAgICAgIHJldHVybiBmb3JOdW1iZXIodmFsdWUpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIE9uZW9mRmllbGRDYXNlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgICBzd2l0Y2ggKHZhbHVlKSB7CiAgICAgICAgICBjYXNlIDExMTogcmV0dXJuIE9ORU9GX1VJTlQzMjsKICAgICAgICAgIGNhc2UgMTEyOiByZXR1cm4gT05FT0ZfTkVTVEVEX01FU1NBR0U7CiAgICAgICAgICBjYXNlIDExMzogcmV0dXJuIE9ORU9GX1NUUklORzsKICAgICAgICAgIGNhc2UgMTE0OiByZXR1cm4gT05FT0ZfQllURVM7CiAgICAgICAgICBjYXNlIDExNTogcmV0dXJuIE9ORU9GX0xBWllfTkVTVEVEX01FU1NBR0U7CiAgICAgICAgICBjYXNlIDExNzogcmV0dXJuIE9ORU9GX05FU1RFRF9NRVNTQUdFMjsKICAgICAgICAgIGNhc2UgMDogcmV0dXJuIE9ORU9GRklFTERfTk9UX1NFVDsKICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE51bWJlcigpIHsKICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgT25lb2ZGaWVsZENhc2UKICAgIGdldE9uZW9mRmllbGRDYXNlKCkgewogICAgICByZXR1cm4gT25lb2ZGaWVsZENhc2UuZm9yTnVtYmVyKAogICAgICAgICAgb25lb2ZGaWVsZENhc2VfKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9JTlQzMl9GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxJbnQzMl8gPSAwOwogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogU2luZ3VsYXIKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEludDMyKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBTaW5ndWxhcgogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0T3B0aW9uYWxJbnQzMigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsSW50MzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0lOVDY0X0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIGxvbmcgb3B0aW9uYWxJbnQ2NF8gPSAwTDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgb3B0aW9uYWxfaW50NjQgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxJbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW50NjQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgb3B0aW9uYWxfaW50NjQgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW50NjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE9wdGlvbmFsSW50NjQoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEludDY0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9VSU5UMzJfRklFTERfTlVNQkVSID0gMzsKICAgIHByaXZhdGUgaW50IG9wdGlvbmFsVWludDMyXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBvcHRpb25hbF91aW50MzIgPSAzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFVpbnQzMigpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgb3B0aW9uYWxfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFVpbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRPcHRpb25hbFVpbnQzMigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsVWludDMyXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9VSU5UNjRfRklFTERfTlVNQkVSID0gNDsKICAgIHByaXZhdGUgbG9uZyBvcHRpb25hbFVpbnQ2NF8gPSAwTDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IG9wdGlvbmFsX3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFVpbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsVWludDY0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQ2NCBvcHRpb25hbF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsVWludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRPcHRpb25hbFVpbnQ2NCgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsVWludDY0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9TSU5UMzJfRklFTERfTlVNQkVSID0gNTsKICAgIHByaXZhdGUgaW50IG9wdGlvbmFsU2ludDMyXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQzMiBvcHRpb25hbF9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFNpbnQzMigpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgb3B0aW9uYWxfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFNpbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRPcHRpb25hbFNpbnQzMigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsU2ludDMyXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9TSU5UNjRfRklFTERfTlVNQkVSID0gNjsKICAgIHByaXZhdGUgbG9uZyBvcHRpb25hbFNpbnQ2NF8gPSAwTDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IG9wdGlvbmFsX3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFNpbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU2ludDY0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBvcHRpb25hbF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRPcHRpb25hbFNpbnQ2NCgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsU2ludDY0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9GSVhFRDMyX0ZJRUxEX05VTUJFUiA9IDc7CiAgICBwcml2YXRlIGludCBvcHRpb25hbEZpeGVkMzJfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBvcHRpb25hbF9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRml4ZWQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsRml4ZWQzMigpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwNDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIG9wdGlvbmFsX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRml4ZWQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRPcHRpb25hbEZpeGVkMzIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEZpeGVkMzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0ZJWEVENjRfRklFTERfTlVNQkVSID0gODsKICAgIHByaXZhdGUgbG9uZyBvcHRpb25hbEZpeGVkNjRfID0gMEw7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgb3B0aW9uYWxfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZpeGVkNjQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDgwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQ2NCBvcHRpb25hbF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZpeGVkNjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE9wdGlvbmFsRml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsRml4ZWQ2NF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfU0ZJWEVEMzJfRklFTERfTlVNQkVSID0gOTsKICAgIHByaXZhdGUgaW50IG9wdGlvbmFsU2ZpeGVkMzJfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgb3B0aW9uYWxfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTZml4ZWQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU2ZpeGVkMzIoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMTAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgb3B0aW9uYWxfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ZpeGVkMzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0T3B0aW9uYWxTZml4ZWQzMigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsU2ZpeGVkMzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NGSVhFRDY0X0ZJRUxEX05VTUJFUiA9IDEwOwogICAgcHJpdmF0ZSBsb25nIG9wdGlvbmFsU2ZpeGVkNjRfID0gMEw7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IG9wdGlvbmFsX3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFNmaXhlZDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxTZml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAyMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBvcHRpb25hbF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ZpeGVkNjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE9wdGlvbmFsU2ZpeGVkNjQoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbFNmaXhlZDY0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9GTE9BVF9GSUVMRF9OVU1CRVIgPSAxMTsKICAgIHByaXZhdGUgZmxvYXQgb3B0aW9uYWxGbG9hdF8gPSAwRjsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgb3B0aW9uYWxfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRmxvYXQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZsb2F0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDQwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IG9wdGlvbmFsX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxGbG9hdC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZsb2F0IGdldE9wdGlvbmFsRmxvYXQoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEZsb2F0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9ET1VCTEVfRklFTERfTlVNQkVSID0gMTI7CiAgICBwcml2YXRlIGRvdWJsZSBvcHRpb25hbERvdWJsZV8gPSAwRDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIG9wdGlvbmFsX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxEb3VibGUgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbERvdWJsZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDA4MDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgb3B0aW9uYWxfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxEb3VibGUuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBkb3VibGUgZ2V0T3B0aW9uYWxEb3VibGUoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbERvdWJsZV87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfQk9PTF9GSUVMRF9OVU1CRVIgPSAxMzsKICAgIHByaXZhdGUgYm9vbGVhbiBvcHRpb25hbEJvb2xfID0gZmFsc2U7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgb3B0aW9uYWxfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxCb29sIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxCb29sKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMTAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgb3B0aW9uYWxfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQm9vbC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZ2V0T3B0aW9uYWxCb29sKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxCb29sXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9TVFJJTkdfRklFTERfTlVNQkVSID0gMTQ7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgdm9sYXRpbGUgamF2YS5sYW5nLk9iamVjdCBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFN0cmluZygpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDIwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTdHJpbmcuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE9wdGlvbmFsU3RyaW5nKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IG9wdGlvbmFsU3RyaW5nXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICBvcHRpb25hbFN0cmluZ18gPSBzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gczsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9wdGlvbmFsU3RyaW5nLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T3B0aW9uYWxTdHJpbmdCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ187CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGI7CiAgICAgICAgcmV0dXJuIGI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0JZVEVTX0ZJRUxEX05VTUJFUiA9IDE1OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgb3B0aW9uYWxCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIG9wdGlvbmFsX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxCeXRlcygpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDQwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQnl0ZXMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T3B0aW9uYWxCeXRlcygpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsQnl0ZXNfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMR1JPVVBfRklFTERfTlVNQkVSID0gMTY7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBvcHRpb25hbEdyb3VwXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsZ3JvdXAgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEdyb3VwKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwODAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxNiB7IC4uLiB9PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxncm91cC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxHcm91cF8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlciBnZXRPcHRpb25hbEdyb3VwT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxHcm91cF8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX05FU1RFRF9NRVNTQUdFX0ZJRUxEX05VTUJFUiA9IDE4OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2UgPSAxODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsTmVzdGVkTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsTmVzdGVkTWVzc2FnZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMTAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTmVzdGVkTWVzc2FnZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0ZPUkVJR05fTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAxOTsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9mb3JlaWduX21lc3NhZ2UgPSAxOTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAyMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxGb3JlaWduTWVzc2FnZV87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfSU1QT1JUX01FU1NBR0VfRklFTERfTlVNQkVSID0gMjA7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV87CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW1wb3J0TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW1wb3J0TWVzc2FnZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwNDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbXBvcnRNZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEltcG9ydE1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEltcG9ydE1lc3NhZ2VfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX05FU1RFRF9FTlVNX0ZJRUxEX05VTUJFUiA9IDIxOwogICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxOZXN0ZWRFbnVtXyA9IDE7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIG9wdGlvbmFsX25lc3RlZF9lbnVtID0gMjE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbE5lc3RlZEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsTmVzdGVkRW51bSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwODAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBvcHRpb25hbF9uZXN0ZWRfZW51bSA9IDIxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTmVzdGVkRW51bS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGdldE9wdGlvbmFsTmVzdGVkRW51bSgpIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5mb3JOdW1iZXIob3B0aW9uYWxOZXN0ZWRFbnVtXyk7CiAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5GT08gOiByZXN1bHQ7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfRk9SRUlHTl9FTlVNX0ZJRUxEX05VTUJFUiA9IDIyOwogICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxGb3JlaWduRW51bV8gPSA0OwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9mb3JlaWduX2VudW0gPSAyMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRm9yZWlnbkVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsRm9yZWlnbkVudW0oKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMTAwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9lbnVtID0gMjI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxGb3JlaWduRW51bS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldE9wdGlvbmFsRm9yZWlnbkVudW0oKSB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKG9wdGlvbmFsRm9yZWlnbkVudW1fKTsKICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLkZPUkVJR05fTElURV9GT08gOiByZXN1bHQ7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfSU1QT1JUX0VOVU1fRklFTERfTlVNQkVSID0gMjM7CiAgICBwcml2YXRlIGludCBvcHRpb25hbEltcG9ydEVudW1fID0gNzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBvcHRpb25hbF9pbXBvcnRfZW51bSA9IDIzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxJbXBvcnRFbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEltcG9ydEVudW0oKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMjAwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBvcHRpb25hbF9pbXBvcnRfZW51bSA9IDIzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW1wb3J0RW51bS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0T3B0aW9uYWxJbXBvcnRFbnVtKCkgewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5mb3JOdW1iZXIob3B0aW9uYWxJbXBvcnRFbnVtXyk7CiAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLklNUE9SVF9MSVRFX0ZPTyA6IHJlc3VsdDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSID0gMjQ7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgdm9sYXRpbGUgamF2YS5sYW5nLk9iamVjdCBvcHRpb25hbFN0cmluZ1BpZWNlXyA9ICIiOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nX3BpZWNlID0gMjQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU3RyaW5nUGllY2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFN0cmluZ1BpZWNlKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDQwMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE9wdGlvbmFsU3RyaW5nUGllY2UoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxTdHJpbmdQaWVjZV87CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gCiAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgb3B0aW9uYWxTdHJpbmdQaWVjZV8gPSBzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gczsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nX3BpZWNlID0gMjQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxTdHJpbmdQaWVjZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9wdGlvbmFsU3RyaW5nUGllY2VCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ1BpZWNlXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgb3B0aW9uYWxTdHJpbmdQaWVjZV8gPSBiOwogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9DT1JEX0ZJRUxEX05VTUJFUiA9IDI1OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIHZvbGF0aWxlIGphdmEubGFuZy5PYmplY3Qgb3B0aW9uYWxDb3JkXyA9ICIiOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxDb3JkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxDb3JkKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDgwMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9jb3JkID0gMjUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxDb3JkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPcHRpb25hbENvcmQoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxDb3JkXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICBvcHRpb25hbENvcmRfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX2NvcmQgPSAyNSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxDb3JkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T3B0aW9uYWxDb3JkQnl0ZXMoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxDb3JkXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgb3B0aW9uYWxDb3JkXyA9IGI7CiAgICAgICAgcmV0dXJuIGI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1BVQkxJQ19JTVBPUlRfTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAyNjsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXzsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIERlZmluZWQgaW4gdW5pdHRlc3RfaW1wb3J0X3B1YmxpYy5wcm90bwogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2UgPSAyNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDEwMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIERlZmluZWQgaW4gdW5pdHRlc3RfaW1wb3J0X3B1YmxpYy5wcm90bwogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2UgPSAyNjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfTEFaWV9NRVNTQUdFX0ZJRUxEX05VTUJFUiA9IDI3OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxMYXp5TWVzc2FnZV87CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbExhenlNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxMYXp5TWVzc2FnZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDIwMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTGF6eU1lc3NhZ2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZSgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsTGF6eU1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbExhenlNZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbGF6eV9tZXNzYWdlID0gMjcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsTGF6eU1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbExhenlNZXNzYWdlXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9VTlZFUklGSUVEX0xBWllfTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAyODsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwNDAwMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDMxOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEludDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBSZXBlYXRlZAogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAzMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFJlcGVhdGVkCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDMxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogUmVwZWF0ZWQKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMzE7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9JTlQ2NF9GSUVMRF9OVU1CRVIgPSAzMjsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHJlcGVhdGVkSW50NjRfID0KICAgICAgICBlbXB0eUxvbmdMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHJlcGVhdGVkX2ludDY0ID0gMzI7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbnQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgIGdldFJlcGVhdGVkSW50NjRMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHJlcGVhdGVkX2ludDY0ID0gMzI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbnQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDY0Q291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDY0Xy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHJlcGVhdGVkX2ludDY0ID0gMzI7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGxvbmcgZ2V0UmVwZWF0ZWRJbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50NjRfLmdldExvbmcoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1VJTlQzMl9GSUVMRF9OVU1CRVIgPSAzMzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRVaW50MzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHJlcGVhdGVkX3VpbnQzMiA9IDMzOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkVWludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UmVwZWF0ZWRVaW50MzJMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRVaW50MzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcmVwZWF0ZWRfdWludDMyID0gMzM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRVaW50MzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRVaW50MzJDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkVWludDMyXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiByZXBlYXRlZF91aW50MzIgPSAzMzs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkVWludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZFVpbnQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkVWludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1VJTlQ2NF9GSUVMRF9OVU1CRVIgPSAzNDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHJlcGVhdGVkVWludDY0XyA9CiAgICAgICAgZW1wdHlMb25nTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcmVwZWF0ZWRfdWludDY0ID0gMzQ7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRVaW50NjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICBnZXRSZXBlYXRlZFVpbnQ2NExpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZFVpbnQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCByZXBlYXRlZF91aW50NjQgPSAzNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFVpbnQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZFVpbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRVaW50NjRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHJlcGVhdGVkX3VpbnQ2NCA9IDM0OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRVaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgbG9uZyBnZXRSZXBlYXRlZFVpbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkVWludDY0Xy5nZXRMb25nKGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TSU5UMzJfRklFTERfTlVNQkVSID0gMzU7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkU2ludDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiByZXBlYXRlZF9zaW50MzIgPSAzNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFNpbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFJlcGVhdGVkU2ludDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHJlcGVhdGVkX3NpbnQzMiA9IDM1OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU2ludDMyLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkU2ludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZFNpbnQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcmVwZWF0ZWRfc2ludDMyID0gMzU7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFNpbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTaW50MzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZFNpbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TSU5UNjRfRklFTERfTlVNQkVSID0gMzY7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCByZXBlYXRlZFNpbnQ2NF8gPQogICAgICAgIGVtcHR5TG9uZ0xpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHJlcGVhdGVkX3NpbnQ2NCA9IDM2OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU2ludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgZ2V0UmVwZWF0ZWRTaW50NjRMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTaW50NjRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcmVwZWF0ZWRfc2ludDY0ID0gMzY7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTaW50NjQuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTaW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ludDY0Xy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCByZXBlYXRlZF9zaW50NjQgPSAzNjs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU2ludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGxvbmcgZ2V0UmVwZWF0ZWRTaW50NjQoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZFNpbnQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRklYRUQzMl9GSUVMRF9OVU1CRVIgPSAzNzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRGaXhlZDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDM3OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAzNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMzc7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GSVhFRDY0X0ZJRUxEX05VTUJFUiA9IDM4OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcmVwZWF0ZWRGaXhlZDY0XyA9CiAgICAgICAgZW1wdHlMb25nTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHJlcGVhdGVkX2ZpeGVkNjQgPSAzODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZpeGVkNjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICBnZXRSZXBlYXRlZEZpeGVkNjRMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDY0XzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCByZXBlYXRlZF9maXhlZDY0ID0gMzg7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGaXhlZDY0LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRml4ZWQ2NENvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDY0Xy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGaXhlZDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGxvbmcgZ2V0UmVwZWF0ZWRGaXhlZDY0KGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDY0Xy5nZXRMb25nKGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TRklYRUQzMl9GSUVMRF9OVU1CRVIgPSAzOTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRTZml4ZWQzMl8gPQogICAgICAgIGVtcHR5SW50TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiByZXBlYXRlZF9zZml4ZWQzMiA9IDM5OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU2ZpeGVkMzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRSZXBlYXRlZFNmaXhlZDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ZpeGVkMzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiByZXBlYXRlZF9zZml4ZWQzMiA9IDM5OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU2ZpeGVkMzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTZml4ZWQzMkNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTZml4ZWQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiByZXBlYXRlZF9zZml4ZWQzMiA9IDM5OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTZml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTZml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ZpeGVkMzJfLmdldEludChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfU0ZJWEVENjRfRklFTERfTlVNQkVSID0gNDA7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCByZXBlYXRlZFNmaXhlZDY0XyA9CiAgICAgICAgZW1wdHlMb25nTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCByZXBlYXRlZF9zZml4ZWQ2NCA9IDQwOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU2ZpeGVkNjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICBnZXRSZXBlYXRlZFNmaXhlZDY0TGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ZpeGVkNjRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCByZXBlYXRlZF9zZml4ZWQ2NCA9IDQwOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU2ZpeGVkNjQuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTZml4ZWQ2NENvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTZml4ZWQ2NF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCByZXBlYXRlZF9zZml4ZWQ2NCA9IDQwOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTZml4ZWQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBsb25nIGdldFJlcGVhdGVkU2ZpeGVkNjQoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZFNmaXhlZDY0Xy5nZXRMb25nKGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GTE9BVF9GSUVMRF9OVU1CRVIgPSA0MTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkZsb2F0TGlzdCByZXBlYXRlZEZsb2F0XyA9CiAgICAgICAgZW1wdHlGbG9hdExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcmVwZWF0ZWRfZmxvYXQgPSA0MTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZsb2F0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkZsb2F0PgogICAgICAgIGdldFJlcGVhdGVkRmxvYXRMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGbG9hdF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHJlcGVhdGVkX2Zsb2F0ID0gNDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGbG9hdC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZsb2F0Q291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZsb2F0Xy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHJlcGVhdGVkX2Zsb2F0ID0gNDE7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZsb2F0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGZsb2F0IGdldFJlcGVhdGVkRmxvYXQoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZsb2F0Xy5nZXRGbG9hdChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRE9VQkxFX0ZJRUxEX05VTUJFUiA9IDQyOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRG91YmxlTGlzdCByZXBlYXRlZERvdWJsZV8gPQogICAgICAgIGVtcHR5RG91YmxlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcmVwZWF0ZWRfZG91YmxlID0gNDI7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWREb3VibGUuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRG91YmxlPgogICAgICAgIGdldFJlcGVhdGVkRG91YmxlTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRG91YmxlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHJlcGVhdGVkX2RvdWJsZSA9IDQyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRG91YmxlLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRG91YmxlQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZERvdWJsZV8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcmVwZWF0ZWRfZG91YmxlID0gNDI7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZERvdWJsZSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBkb3VibGUgZ2V0UmVwZWF0ZWREb3VibGUoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZERvdWJsZV8uZ2V0RG91YmxlKGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9CT09MX0ZJRUxEX05VTUJFUiA9IDQzOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuQm9vbGVhbkxpc3QgcmVwZWF0ZWRCb29sXyA9CiAgICAgICAgZW1wdHlCb29sZWFuTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHJlcGVhdGVkX2Jvb2wgPSA0Mzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEJvb2wuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuQm9vbGVhbj4KICAgICAgICBnZXRSZXBlYXRlZEJvb2xMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRCb29sXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCByZXBlYXRlZF9ib29sID0gNDM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRCb29sLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkQm9vbENvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRCb29sXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRCb29sIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGJvb2xlYW4gZ2V0UmVwZWF0ZWRCb29sKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRCb29sXy5nZXRCb29sZWFuKGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TVFJJTkdfRklFTERfTlVNQkVSID0gNDQ7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0IHJlcGVhdGVkU3RyaW5nXyA9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nID0gNDQ7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTdHJpbmcuCiAgICAgKi8KICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sU3RyaW5nTGlzdAogICAgICAgIGdldFJlcGVhdGVkU3RyaW5nTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZyA9IDQ0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkU3RyaW5nQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZFN0cmluZ18uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nID0gNDQ7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFN0cmluZyBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldFJlcGVhdGVkU3RyaW5nKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB2YWx1ZSB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBvZiB0aGUgcmVwZWF0ZWRTdHJpbmcgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdCeXRlcyhpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nXy5nZXRCeXRlU3RyaW5nKGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9CWVRFU19GSUVMRF9OVU1CRVIgPSA0NTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLlByb3RvYnVmTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IHJlcGVhdGVkQnl0ZXNfID0KICAgICAgICBlbXB0eUxpc3QoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNsYXNzKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEJ5dGVzLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgICAgIGdldFJlcGVhdGVkQnl0ZXNMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRCeXRlc187CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJ5dGVzIHJlcGVhdGVkX2J5dGVzID0gNDU7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRCeXRlcy4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEJ5dGVzQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEJ5dGVzXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJ5dGVzIHJlcGVhdGVkX2J5dGVzID0gNDU7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEJ5dGVzIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRSZXBlYXRlZEJ5dGVzKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRCeXRlc18uZ2V0KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFREdST1VQX0ZJRUxEX05VTUJFUiA9IDQ2OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cD4gcmVwZWF0ZWRHcm91cF87CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwPiBnZXRSZXBlYXRlZEdyb3VwTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXI+IAogICAgICAgIGdldFJlcGVhdGVkR3JvdXBPckJ1aWxkZXJMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkR3JvdXBDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgZ2V0UmVwZWF0ZWRHcm91cChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyIGdldFJlcGVhdGVkR3JvdXBPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwXy5nZXQoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX05FU1RFRF9NRVNTQUdFX0ZJRUxEX05VTUJFUiA9IDQ4OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXzsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZU9yQnVpbGRlckxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2UoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZU9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GT1JFSUdOX01FU1NBR0VfRklFTERfTlVNQkVSID0gNDk7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXzsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlT3JCdWlsZGVyKAogICAgICAgIGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9JTVBPUlRfTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSA1MDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZT4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXzsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlPiBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZU9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9ORVNURURfRU5VTV9GSUVMRF9OVU1CRVIgPSA1MTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gcmVwZWF0ZWROZXN0ZWRFbnVtXzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+IHJlcGVhdGVkTmVzdGVkRW51bV9jb252ZXJ0ZXJfID0KICAgICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bT4oKSB7CiAgICAgICAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBjb252ZXJ0KGphdmEubGFuZy5JbnRlZ2VyIGZyb20pIHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uZm9yTnVtYmVyKGZyb20pOwogICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLkZPTyA6IHJlc3VsdDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH07CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWROZXN0ZWRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtPiBnZXRSZXBlYXRlZE5lc3RlZEVudW1MaXN0KCkgewogICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtPihyZXBlYXRlZE5lc3RlZEVudW1fLCByZXBlYXRlZE5lc3RlZEVudW1fY29udmVydGVyXyk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWROZXN0ZWRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkTmVzdGVkRW51bUNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRFbnVtXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZE5lc3RlZEVudW0gYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGdldFJlcGVhdGVkTmVzdGVkRW51bShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkRW51bV9jb252ZXJ0ZXJfLmNvbnZlcnQocmVwZWF0ZWROZXN0ZWRFbnVtXy5nZXQoaW5kZXgpKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GT1JFSUdOX0VOVU1fRklFTERfTlVNQkVSID0gNTI7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IHJlcGVhdGVkRm9yZWlnbkVudW1fOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5MaXN0QWRhcHRlci5Db252ZXJ0ZXI8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZT4gcmVwZWF0ZWRGb3JlaWduRW51bV9jb252ZXJ0ZXJfID0KICAgICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZT4oKSB7CiAgICAgICAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBjb252ZXJ0KGphdmEubGFuZy5JbnRlZ2VyIGZyb20pIHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKGZyb20pOwogICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLkZPUkVJR05fTElURV9GT08gOiByZXN1bHQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9OwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZvcmVpZ25FbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPiBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtTGlzdCgpIHsKICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZT4ocmVwZWF0ZWRGb3JlaWduRW51bV8sIHJlcGVhdGVkRm9yZWlnbkVudW1fY29udmVydGVyXyk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHJlcGVhdGVkX2ZvcmVpZ25fZW51bSA9IDUyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRm9yZWlnbkVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGb3JlaWduRW51bUNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduRW51bV8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRm9yZWlnbkVudW0gYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldFJlcGVhdGVkRm9yZWlnbkVudW0oaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25FbnVtX2NvbnZlcnRlcl8uY29udmVydChyZXBlYXRlZEZvcmVpZ25FbnVtXy5nZXQoaW5kZXgpKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9JTVBPUlRfRU5VTV9GSUVMRF9OVU1CRVIgPSA1MzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gcmVwZWF0ZWRJbXBvcnRFbnVtXzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4gcmVwZWF0ZWRJbXBvcnRFbnVtX2NvbnZlcnRlcl8gPQogICAgICAgICAgICBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5MaXN0QWRhcHRlci5Db252ZXJ0ZXI8CiAgICAgICAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGU+KCkgewogICAgICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSBjb252ZXJ0KGphdmEubGFuZy5JbnRlZ2VyIGZyb20pIHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLmZvck51bWJlcihmcm9tKTsKICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLklNUE9SVF9MSVRFX0ZPTyA6IHJlc3VsdDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH07CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEltcG9ydEVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4gZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtTGlzdCgpIHsKICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlPihyZXBlYXRlZEltcG9ydEVudW1fLCByZXBlYXRlZEltcG9ydEVudW1fY29udmVydGVyXyk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEltcG9ydEVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydEVudW1fLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSByZXBlYXRlZF9pbXBvcnRfZW51bSA9IDUzOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbXBvcnRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIGdldFJlcGVhdGVkSW1wb3J0RW51bShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0RW51bV9jb252ZXJ0ZXJfLmNvbnZlcnQocmVwZWF0ZWRJbXBvcnRFbnVtXy5nZXQoaW5kZXgpKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSID0gNTQ7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0IHJlcGVhdGVkU3RyaW5nUGllY2VfID0KICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sU3RyaW5nTGlzdAogICAgICAgIGdldFJlcGVhdGVkU3RyaW5nUGllY2VMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdQaWVjZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdQaWVjZV8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU3RyaW5nUGllY2UgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdQaWVjZV8uZ2V0KGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdmFsdWUgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkU3RyaW5nUGllY2UgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUJ5dGVzKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdQaWVjZV8uZ2V0Qnl0ZVN0cmluZyhpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfQ09SRF9GSUVMRF9OVU1CRVIgPSA1NTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QgcmVwZWF0ZWRDb3JkXyA9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkQ29yZC4KICAgICAqLwogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xTdHJpbmdMaXN0CiAgICAgICAgZ2V0UmVwZWF0ZWRDb3JkTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkQ29yZF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRDb3JkLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkQ29yZENvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRDb3JkXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZENvcmQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRSZXBlYXRlZENvcmQoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZENvcmRfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdmFsdWUgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkQ29yZCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRSZXBlYXRlZENvcmRCeXRlcyhpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkQ29yZF8uZ2V0Qnl0ZVN0cmluZyhpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfTEFaWV9NRVNTQUdFX0ZJRUxEX05VTUJFUiA9IDU3OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gcmVwZWF0ZWRMYXp5TWVzc2FnZV87CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiBnZXRSZXBlYXRlZExhenlNZXNzYWdlTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VPckJ1aWxkZXJMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZExhenlNZXNzYWdlXy5nZXQoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfSU5UMzJfRklFTERfTlVNQkVSID0gNjE7CiAgICBwcml2YXRlIGludCBkZWZhdWx0SW50MzJfID0gNDE7CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBTaW5ndWxhciB3aXRoIGRlZmF1bHRzCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWZhdWx0X2ludDMyID0gNjEgW2RlZmF1bHQgPSA0MV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0SW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0SW50MzIoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDA4MDAwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFNpbmd1bGFyIHdpdGggZGVmYXVsdHMKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlZmF1bHRfaW50MzIgPSA2MSBbZGVmYXVsdCA9IDQxXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0SW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0RGVmYXVsdEludDMyKCkgewogICAgICByZXR1cm4gZGVmYXVsdEludDMyXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0lOVDY0X0ZJRUxEX05VTUJFUiA9IDYyOwogICAgcHJpdmF0ZSBsb25nIGRlZmF1bHRJbnQ2NF8gPSA0Mkw7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGRlZmF1bHRfaW50NjQgPSA2MiBbZGVmYXVsdCA9IDQyXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRJbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRJbnQ2NCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MTAwMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBkZWZhdWx0X2ludDY0ID0gNjIgW2RlZmF1bHQgPSA0Ml07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdEludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXREZWZhdWx0SW50NjQoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0SW50NjRfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfVUlOVDMyX0ZJRUxEX05VTUJFUiA9IDYzOwogICAgcHJpdmF0ZSBpbnQgZGVmYXVsdFVpbnQzMl8gPSA0MzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIGRlZmF1bHRfdWludDMyID0gNjMgW2RlZmF1bHQgPSA0M107PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0VWludDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdFVpbnQzMigpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MjAwMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgZGVmYXVsdF91aW50MzIgPSA2MyBbZGVmYXVsdCA9IDQzXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0VWludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldERlZmF1bHRVaW50MzIoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0VWludDMyXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1VJTlQ2NF9GSUVMRF9OVU1CRVIgPSA2NDsKICAgIHByaXZhdGUgbG9uZyBkZWZhdWx0VWludDY0XyA9IDQ0TDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IGRlZmF1bHRfdWludDY0ID0gNjQgW2RlZmF1bHQgPSA0NF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0VWludDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdFVpbnQ2NCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4NDAwMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50NjQgZGVmYXVsdF91aW50NjQgPSA2NCBbZGVmYXVsdCA9IDQ0XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0VWludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXREZWZhdWx0VWludDY0KCkgewogICAgICByZXR1cm4gZGVmYXVsdFVpbnQ2NF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9TSU5UMzJfRklFTERfTlVNQkVSID0gNjU7CiAgICBwcml2YXRlIGludCBkZWZhdWx0U2ludDMyXyA9IC00NTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIGRlZmF1bHRfc2ludDMyID0gNjUgW2RlZmF1bHQgPSAtNDVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFNpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTaW50MzIoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDgwMDAwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIGRlZmF1bHRfc2ludDMyID0gNjUgW2RlZmF1bHQgPSAtNDVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTaW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0RGVmYXVsdFNpbnQzMigpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRTaW50MzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU0lOVDY0X0ZJRUxEX05VTUJFUiA9IDY2OwogICAgcHJpdmF0ZSBsb25nIGRlZmF1bHRTaW50NjRfID0gNDZMOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50NjQgZGVmYXVsdF9zaW50NjQgPSA2NiBbZGVmYXVsdCA9IDQ2XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTaW50NjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0U2ludDY0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBkZWZhdWx0X3NpbnQ2NCA9IDY2IFtkZWZhdWx0ID0gNDZdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTaW50NjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldERlZmF1bHRTaW50NjQoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0U2ludDY0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0ZJWEVEMzJfRklFTERfTlVNQkVSID0gNjc7CiAgICBwcml2YXRlIGludCBkZWZhdWx0Rml4ZWQzMl8gPSA0NzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBkZWZhdWx0X2ZpeGVkMzIgPSA2NyBbZGVmYXVsdCA9IDQ3XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRGaXhlZDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEZpeGVkMzIoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBkZWZhdWx0X2ZpeGVkMzIgPSA2NyBbZGVmYXVsdCA9IDQ3XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Rml4ZWQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXREZWZhdWx0Rml4ZWQzMigpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRGaXhlZDMyXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0ZJWEVENjRfRklFTERfTlVNQkVSID0gNjg7CiAgICBwcml2YXRlIGxvbmcgZGVmYXVsdEZpeGVkNjRfID0gNDhMOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IGRlZmF1bHRfZml4ZWQ2NCA9IDY4IFtkZWZhdWx0ID0gNDhdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Rml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDAwMDQpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IGRlZmF1bHRfZml4ZWQ2NCA9IDY4IFtkZWZhdWx0ID0gNDhdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGaXhlZDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXREZWZhdWx0Rml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRGaXhlZDY0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1NGSVhFRDMyX0ZJRUxEX05VTUJFUiA9IDY5OwogICAgcHJpdmF0ZSBpbnQgZGVmYXVsdFNmaXhlZDMyXyA9IDQ5OwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQzMiBkZWZhdWx0X3NmaXhlZDMyID0gNjkgW2RlZmF1bHQgPSA0OV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U2ZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0U2ZpeGVkMzIoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDA4KSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgZGVmYXVsdF9zZml4ZWQzMiA9IDY5IFtkZWZhdWx0ID0gNDldOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTZml4ZWQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXREZWZhdWx0U2ZpeGVkMzIoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0U2ZpeGVkMzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU0ZJWEVENjRfRklFTERfTlVNQkVSID0gNzA7CiAgICBwcml2YXRlIGxvbmcgZGVmYXVsdFNmaXhlZDY0XyA9IC01MEw7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IGRlZmF1bHRfc2ZpeGVkNjQgPSA3MCBbZGVmYXVsdCA9IC01MF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U2ZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0U2ZpeGVkNjQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDEwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgZGVmYXVsdF9zZml4ZWQ2NCA9IDcwIFtkZWZhdWx0ID0gLTUwXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U2ZpeGVkNjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldERlZmF1bHRTZml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRTZml4ZWQ2NF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9GTE9BVF9GSUVMRF9OVU1CRVIgPSA3MTsKICAgIHByaXZhdGUgZmxvYXQgZGVmYXVsdEZsb2F0XyA9IDUxLjVGOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmbG9hdCBkZWZhdWx0X2Zsb2F0ID0gNzEgW2RlZmF1bHQgPSA1MS41XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRGbG9hdCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRGbG9hdCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDAwMjApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmbG9hdCBkZWZhdWx0X2Zsb2F0ID0gNzEgW2RlZmF1bHQgPSA1MS41XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0RmxvYXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmbG9hdCBnZXREZWZhdWx0RmxvYXQoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0RmxvYXRfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfRE9VQkxFX0ZJRUxEX05VTUJFUiA9IDcyOwogICAgcHJpdmF0ZSBkb3VibGUgZGVmYXVsdERvdWJsZV8gPSA1MjAwMEQ7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBkZWZhdWx0X2RvdWJsZSA9IDcyIFtkZWZhdWx0ID0gNTIwMDBdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdERvdWJsZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHREb3VibGUoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDQwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIGRlZmF1bHRfZG91YmxlID0gNzIgW2RlZmF1bHQgPSA1MjAwMF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdERvdWJsZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGRvdWJsZSBnZXREZWZhdWx0RG91YmxlKCkgewogICAgICByZXR1cm4gZGVmYXVsdERvdWJsZV87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9CT09MX0ZJRUxEX05VTUJFUiA9IDczOwogICAgcHJpdmF0ZSBib29sZWFuIGRlZmF1bHRCb29sXyA9IHRydWU7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgZGVmYXVsdF9ib29sID0gNzMgW2RlZmF1bHQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRCb29sIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEJvb2woKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDgwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBkZWZhdWx0X2Jvb2wgPSA3MyBbZGVmYXVsdCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRCb29sLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBnZXREZWZhdWx0Qm9vbCgpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRCb29sXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1NUUklOR19GSUVMRF9OVU1CRVIgPSA3NDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSB2b2xhdGlsZSBqYXZhLmxhbmcuT2JqZWN0IGRlZmF1bHRTdHJpbmdfID0gImhlbGxvIjsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0U3RyaW5nKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwMDEwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZyA9IDc0IFtkZWZhdWx0ID0gImhlbGxvIl07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdFN0cmluZy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdFN0cmluZygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0U3RyaW5nXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICBkZWZhdWx0U3RyaW5nXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZyA9IDc0IFtkZWZhdWx0ID0gImhlbGxvIl07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlZmF1bHRTdHJpbmcuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZWZhdWx0U3RyaW5nQnl0ZXMoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVmYXVsdFN0cmluZ187CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIGRlZmF1bHRTdHJpbmdfID0gYjsKICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9CWVRFU19GSUVMRF9OVU1CRVIgPSA3NTsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRlZmF1bHRCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmJ5dGVzRGVmYXVsdFZhbHVlKCJ3b3JsZCIpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBkZWZhdWx0X2J5dGVzID0gNzUgW2RlZmF1bHQgPSAid29ybGQiXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRCeXRlcygpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDAyMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBkZWZhdWx0X2J5dGVzID0gNzUgW2RlZmF1bHQgPSAid29ybGQiXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Qnl0ZXMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0RGVmYXVsdEJ5dGVzKCkgewogICAgICByZXR1cm4gZGVmYXVsdEJ5dGVzXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX05FU1RFRF9FTlVNX0ZJRUxEX05VTUJFUiA9IDgxOwogICAgcHJpdmF0ZSBpbnQgZGVmYXVsdE5lc3RlZEVudW1fID0gMjsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gZGVmYXVsdF9uZXN0ZWRfZW51bSA9IDgxIFtkZWZhdWx0ID0gQkFSXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHROZXN0ZWRFbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0TmVzdGVkRW51bSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDA0MDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBkZWZhdWx0X25lc3RlZF9lbnVtID0gODEgW2RlZmF1bHQgPSBCQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHROZXN0ZWRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gZ2V0RGVmYXVsdE5lc3RlZEVudW0oKSB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uZm9yTnVtYmVyKGRlZmF1bHROZXN0ZWRFbnVtXyk7CiAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5CQVIgOiByZXN1bHQ7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9GT1JFSUdOX0VOVU1fRklFTERfTlVNQkVSID0gODI7CiAgICBwcml2YXRlIGludCBkZWZhdWx0Rm9yZWlnbkVudW1fID0gNTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZvcmVpZ25FbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Rm9yZWlnbkVudW0oKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwODAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGb3JlaWduRW51bS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldERlZmF1bHRGb3JlaWduRW51bSgpIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIoZGVmYXVsdEZvcmVpZ25FbnVtXyk7CiAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5GT1JFSUdOX0xJVEVfQkFSIDogcmVzdWx0OwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfSU1QT1JUX0VOVU1fRklFTERfTlVNQkVSID0gODM7CiAgICBwcml2YXRlIGludCBkZWZhdWx0SW1wb3J0RW51bV8gPSA4OwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIGRlZmF1bHRfaW1wb3J0X2VudW0gPSA4MyBbZGVmYXVsdCA9IElNUE9SVF9MSVRFX0JBUl07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0SW1wb3J0RW51bSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEltcG9ydEVudW0oKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAxMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBkZWZhdWx0X2ltcG9ydF9lbnVtID0gODMgW2RlZmF1bHQgPSBJTVBPUlRfTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRJbXBvcnRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSBnZXREZWZhdWx0SW1wb3J0RW51bSgpIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuZm9yTnVtYmVyKGRlZmF1bHRJbXBvcnRFbnVtXyk7CiAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLklNUE9SVF9MSVRFX0JBUiA6IHJlc3VsdDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1NUUklOR19QSUVDRV9GSUVMRF9OVU1CRVIgPSA4NDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSB2b2xhdGlsZSBqYXZhLmxhbmcuT2JqZWN0IGRlZmF1bHRTdHJpbmdQaWVjZV8gPSAiYWJjIjsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nX3BpZWNlID0gODQgW2RlZmF1bHQgPSAiYWJjIiwgY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFN0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdFN0cmluZ1BpZWNlKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwMjAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U3RyaW5nUGllY2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldERlZmF1bHRTdHJpbmdQaWVjZSgpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0U3RyaW5nUGllY2VfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSBzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gczsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmdfcGllY2UgPSA4NCBbZGVmYXVsdCA9ICJhYmMiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlZmF1bHRTdHJpbmdQaWVjZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldERlZmF1bHRTdHJpbmdQaWVjZUJ5dGVzKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlZmF1bHRTdHJpbmdQaWVjZV87CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSBiOwogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0NPUkRfRklFTERfTlVNQkVSID0gODU7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgdm9sYXRpbGUgamF2YS5sYW5nLk9iamVjdCBkZWZhdWx0Q29yZF8gPSAiMTIzIjsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Q29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRDb3JkKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwNDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X2NvcmQgPSA4NSBbZGVmYXVsdCA9ICIxMjMiLCBjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRDb3JkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXREZWZhdWx0Q29yZCgpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0Q29yZF87CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gCiAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgZGVmYXVsdENvcmRfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlZmF1bHRDb3JkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0RGVmYXVsdENvcmRCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0Q29yZF87CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIGRlZmF1bHRDb3JkXyA9IGI7CiAgICAgICAgcmV0dXJuIGI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1VJTlQzMl9GSUVMRF9OVU1CRVIgPSAxMTE7CiAgICAvKioKICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSAxMTE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlVpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mVWludDMyKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDExMTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+dWludDMyIG9uZW9mX3VpbnQzMiA9IDExMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlVpbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRPbmVvZlVpbnQzMigpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTEpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gMDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9ORVNURURfTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAxMTI7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX25lc3RlZF9tZXNzYWdlID0gMTEyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZOZXN0ZWRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZOZXN0ZWRNZXNzYWdlKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDExMjsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZOZXN0ZWRNZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9uZW9mTmVzdGVkTWVzc2FnZSgpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIpIHsKICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX25lc3RlZF9tZXNzYWdlID0gMTEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPbmVvZk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEyKSB7CiAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1NUUklOR19GSUVMRF9OVU1CRVIgPSAxMTM7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAxMTM7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDExMzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZy4KICAgICAqLwogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmcoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gIiI7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpICYmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gczsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZy4KICAgICAqLwogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9uZW9mU3RyaW5nQnl0ZXMoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gIiI7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTMpIHsKICAgICAgICAgIG9uZW9mRmllbGRfID0gYjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX0JZVEVTX0ZJRUxEX05VTUJFUiA9IDExNDsKICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSAxMTQ7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZCeXRlcygpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxMTQ7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gMTE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mQnl0ZXMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlcygpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTQpIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9MQVpZX05FU1RFRF9NRVNTQUdFX0ZJRUxEX05VTUJFUiA9IDExNTsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9sYXp5X25lc3RlZF9tZXNzYWdlID0gMTE1IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNSkgewogICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNSkgewogICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9ORVNURURfTUVTU0FHRTJfRklFTERfTlVNQkVSID0gMTE3OwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZOZXN0ZWRNZXNzYWdlMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mTmVzdGVkTWVzc2FnZTIoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mTmVzdGVkTWVzc2FnZTIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIGdldE9uZW9mTmVzdGVkTWVzc2FnZTIoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSB7CiAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMk9yQnVpbGRlciBnZXRPbmVvZk5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNykgewogICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpIG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFQ0VQVElWRUxZX05BTUVEX0xJU1RfRklFTERfTlVNQkVSID0gMTE2OwogICAgcHJpdmF0ZSBpbnQgZGVjZXB0aXZlbHlOYW1lZExpc3RfID0gMDsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRlc3RzIHRvU3RyaW5nIGZvciBub24tcmVwZWF0ZWQgZmllbGRzIHdpdGggYSBsaXN0IHN1ZmZpeAogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVjZXB0aXZlbHlfbmFtZWRfbGlzdCA9IDExNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlY2VwdGl2ZWx5TmFtZWRMaXN0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVjZXB0aXZlbHlOYW1lZExpc3QoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDA4MDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRlc3RzIHRvU3RyaW5nIGZvciBub24tcmVwZWF0ZWQgZmllbGRzIHdpdGggYSBsaXN0IHN1ZmZpeAogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVjZXB0aXZlbHlfbmFtZWRfbGlzdCA9IDExNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXREZWNlcHRpdmVseU5hbWVkTGlzdCgpIHsKICAgICAgcmV0dXJuIGRlY2VwdGl2ZWx5TmFtZWRMaXN0XzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIG9wdGlvbmFsSW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQ2NCgyLCBvcHRpb25hbEludDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyKDMsIG9wdGlvbmFsVWludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDY0KDQsIG9wdGlvbmFsVWludDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlU0ludDMyKDUsIG9wdGlvbmFsU2ludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlU0ludDY0KDYsIG9wdGlvbmFsU2ludDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwNDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRml4ZWQzMig3LCBvcHRpb25hbEZpeGVkMzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDA4MCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVGaXhlZDY0KDgsIG9wdGlvbmFsRml4ZWQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMTAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVNGaXhlZDMyKDksIG9wdGlvbmFsU2ZpeGVkMzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVTRml4ZWQ2NCgxMCwgb3B0aW9uYWxTZml4ZWQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwNDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUZsb2F0KDExLCBvcHRpb25hbEZsb2F0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRG91YmxlKDEyLCBvcHRpb25hbERvdWJsZV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAxMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUJvb2woMTMsIG9wdGlvbmFsQm9vbF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAyMDAwKSAhPSAwKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgMTQsIG9wdGlvbmFsU3RyaW5nXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDQwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlQnl0ZXMoMTUsIG9wdGlvbmFsQnl0ZXNfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwODAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVHcm91cCgxNiwgZ2V0T3B0aW9uYWxHcm91cCgpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAxMDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDE4LCBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMjAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxOSwgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDA0MDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDIwLCBnZXRPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwODAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSgyMSwgb3B0aW9uYWxOZXN0ZWRFbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAxMDAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSgyMiwgb3B0aW9uYWxGb3JlaWduRW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMjAwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oMjMsIG9wdGlvbmFsSW1wb3J0RW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwNDAwMDAwKSAhPSAwKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgMjQsIG9wdGlvbmFsU3RyaW5nUGllY2VfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDgwMDAwMCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDI1LCBvcHRpb25hbENvcmRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMTAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDI2LCBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDIwMDAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgyNywgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZSgpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwNDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDI4LCBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkSW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMzEsIHJlcGVhdGVkSW50MzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEludDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUludDY0KDMyLCByZXBlYXRlZEludDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkVWludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMigzMywgcmVwZWF0ZWRVaW50MzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFVpbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50NjQoMzQsIHJlcGVhdGVkVWludDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkU2ludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVNJbnQzMigzNSwgcmVwZWF0ZWRTaW50MzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFNpbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVTSW50NjQoMzYsIHJlcGVhdGVkU2ludDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkRml4ZWQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVGaXhlZDMyKDM3LCByZXBlYXRlZEZpeGVkMzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEZpeGVkNjRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRml4ZWQ2NCgzOCwgcmVwZWF0ZWRGaXhlZDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkU2ZpeGVkMzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlU0ZpeGVkMzIoMzksIHJlcGVhdGVkU2ZpeGVkMzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFNmaXhlZDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVNGaXhlZDY0KDQwLCByZXBlYXRlZFNmaXhlZDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkRmxvYXRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRmxvYXQoNDEsIHJlcGVhdGVkRmxvYXRfLmdldEZsb2F0KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkRG91YmxlXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZURvdWJsZSg0MiwgcmVwZWF0ZWREb3VibGVfLmdldERvdWJsZShpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEJvb2xfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlQm9vbCg0MywgcmVwZWF0ZWRCb29sXy5nZXRCb29sZWFuKGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkU3RyaW5nXy5zaXplKCk7IGkrKykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgNDQsIHJlcGVhdGVkU3RyaW5nXy5nZXRSYXcoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRCeXRlc18uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVCeXRlcyg0NSwgcmVwZWF0ZWRCeXRlc18uZ2V0KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkR3JvdXBfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlR3JvdXAoNDYsIHJlcGVhdGVkR3JvdXBfLmdldChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSg0OCwgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDQ5LCByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoNTAsIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uZ2V0KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkTmVzdGVkRW51bV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtKDUxLCByZXBlYXRlZE5lc3RlZEVudW1fLmdldChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEZvcmVpZ25FbnVtXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oNTIsIHJlcGVhdGVkRm9yZWlnbkVudW1fLmdldChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEltcG9ydEVudW1fLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSg1MywgcmVwZWF0ZWRJbXBvcnRFbnVtXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRTdHJpbmdQaWVjZV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDU0LCByZXBlYXRlZFN0cmluZ1BpZWNlXy5nZXRSYXcoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRDb3JkXy5zaXplKCk7IGkrKykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgNTUsIHJlcGVhdGVkQ29yZF8uZ2V0UmF3KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkTGF6eU1lc3NhZ2VfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSg1NywgcmVwZWF0ZWRMYXp5TWVzc2FnZV8uZ2V0KGkpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwODAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMig2MSwgZGVmYXVsdEludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MTAwMDAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50NjQoNjIsIGRlZmF1bHRJbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDIwMDAwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMig2MywgZGVmYXVsdFVpbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDQwMDAwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQ2NCg2NCwgZGVmYXVsdFVpbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDgwMDAwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVNJbnQzMig2NSwgZGVmYXVsdFNpbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVNJbnQ2NCg2NiwgZGVmYXVsdFNpbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUZpeGVkMzIoNjcsIGRlZmF1bHRGaXhlZDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRml4ZWQ2NCg2OCwgZGVmYXVsdEZpeGVkNjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVTRml4ZWQzMig2OSwgZGVmYXVsdFNmaXhlZDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlU0ZpeGVkNjQoNzAsIGRlZmF1bHRTZml4ZWQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDIwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUZsb2F0KDcxLCBkZWZhdWx0RmxvYXRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVEb3VibGUoNzIsIGRlZmF1bHREb3VibGVfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDA4MCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVCb29sKDczLCBkZWZhdWx0Qm9vbF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMTAwKSAhPSAwKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgNzQsIGRlZmF1bHRTdHJpbmdfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVCeXRlcyg3NSwgZGVmYXVsdEJ5dGVzXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDA0MDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSg4MSwgZGVmYXVsdE5lc3RlZEVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDgwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtKDgyLCBkZWZhdWx0Rm9yZWlnbkVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtKDgzLCBkZWZhdWx0SW1wb3J0RW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAyMDAwKSAhPSAwKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgODQsIGRlZmF1bHRTdHJpbmdQaWVjZV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDA0MDAwKSAhPSAwKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgODUsIGRlZmF1bHRDb3JkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTEpIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzIoCiAgICAgICAgICAgIDExMSwgKGludCkoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEyKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxMTIsIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgMTEzLCBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTQpIHsKICAgICAgICBvdXRwdXQud3JpdGVCeXRlcygKICAgICAgICAgICAgMTE0LCAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDExNSwgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDA4MDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDExNiwgZGVjZXB0aXZlbHlOYW1lZExpc3RfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNykgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMTE3LCAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDEsIG9wdGlvbmFsSW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50NjRTaXplKDIsIG9wdGlvbmFsSW50NjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlVUludDMyU2l6ZSgzLCBvcHRpb25hbFVpbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVVSW50NjRTaXplKDQsIG9wdGlvbmFsVWludDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZVNJbnQzMlNpemUoNSwgb3B0aW9uYWxTaW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlU0ludDY0U2l6ZSg2LCBvcHRpb25hbFNpbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVGaXhlZDMyU2l6ZSg3LCBvcHRpb25hbEZpeGVkMzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDA4MCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRml4ZWQ2NFNpemUoOCwgb3B0aW9uYWxGaXhlZDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAxMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZVNGaXhlZDMyU2l6ZSg5LCBvcHRpb25hbFNmaXhlZDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAyMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZVNGaXhlZDY0U2l6ZSgxMCwgb3B0aW9uYWxTZml4ZWQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwNDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVGbG9hdFNpemUoMTEsIG9wdGlvbmFsRmxvYXRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDgwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRG91YmxlU2l6ZSgxMiwgb3B0aW9uYWxEb3VibGVfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlQm9vbFNpemUoMTMsIG9wdGlvbmFsQm9vbF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAyMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoMTQsIG9wdGlvbmFsU3RyaW5nXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDQwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUJ5dGVzU2l6ZSgxNSwgb3B0aW9uYWxCeXRlc18pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDA4MDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVHcm91cFNpemUoMTYsIGdldE9wdGlvbmFsR3JvdXAoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMTAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE4LCBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMjAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE5LCBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDQwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyMCwgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDgwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZSgyMSwgb3B0aW9uYWxOZXN0ZWRFbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAxMDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUVudW1TaXplKDIyLCBvcHRpb25hbEZvcmVpZ25FbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAyMDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUVudW1TaXplKDIzLCBvcHRpb25hbEltcG9ydEVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDQwMDAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmNvbXB1dGVTdHJpbmdTaXplKDI0LCBvcHRpb25hbFN0cmluZ1BpZWNlXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDA4MDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5jb21wdXRlU3RyaW5nU2l6ZSgyNSwgb3B0aW9uYWxDb3JkXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDEwMDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDI2LCBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDIwMDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDI3LCBnZXRPcHRpb25hbExhenlNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDA0MDAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyOCwgZ2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKHJlcGVhdGVkSW50MzJfLmdldEludChpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEludDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDY0U2l6ZU5vVGFnKHJlcGVhdGVkSW50NjRfLmdldExvbmcoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkSW50NjRMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRVaW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlVUludDMyU2l6ZU5vVGFnKHJlcGVhdGVkVWludDMyXy5nZXRJbnQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkVWludDMyTGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkVWludDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZVVJbnQ2NFNpemVOb1RhZyhyZXBlYXRlZFVpbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRVaW50NjRMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRTaW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlU0ludDMyU2l6ZU5vVGFnKHJlcGVhdGVkU2ludDMyXy5nZXRJbnQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkU2ludDMyTGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkU2ludDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZVNJbnQ2NFNpemVOb1RhZyhyZXBlYXRlZFNpbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRTaW50NjRMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gNCAqIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gOCAqIGdldFJlcGVhdGVkRml4ZWQ2NExpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZEZpeGVkNjRMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gNCAqIGdldFJlcGVhdGVkU2ZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRTZml4ZWQzMkxpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZGF0YVNpemUgPSA4ICogZ2V0UmVwZWF0ZWRTZml4ZWQ2NExpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZFNmaXhlZDY0TGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDQgKiBnZXRSZXBlYXRlZEZsb2F0TGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkRmxvYXRMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gOCAqIGdldFJlcGVhdGVkRG91YmxlTGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkRG91YmxlTGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDEgKiBnZXRSZXBlYXRlZEJvb2xMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRCb29sTGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkU3RyaW5nXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tcHV0ZVN0cmluZ1NpemVOb1RhZyhyZXBlYXRlZFN0cmluZ18uZ2V0UmF3KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZFN0cmluZ0xpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEJ5dGVzXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUJ5dGVzU2l6ZU5vVGFnKHJlcGVhdGVkQnl0ZXNfLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRCeXRlc0xpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEdyb3VwXy5zaXplKCk7IGkrKykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVHcm91cFNpemUoNDYsIHJlcGVhdGVkR3JvdXBfLmdldChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDQ4LCByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLmdldChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5zaXplKCk7IGkrKykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg0OSwgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uZ2V0KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNTAsIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uZ2V0KGkpKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkTmVzdGVkRW51bV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZU5vVGFnKHJlcGVhdGVkTmVzdGVkRW51bV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiByZXBlYXRlZE5lc3RlZEVudW1fLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkRm9yZWlnbkVudW1fLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlRW51bVNpemVOb1RhZyhyZXBlYXRlZEZvcmVpZ25FbnVtXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIHJlcGVhdGVkRm9yZWlnbkVudW1fLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkSW1wb3J0RW51bV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZU5vVGFnKHJlcGVhdGVkSW1wb3J0RW51bV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiByZXBlYXRlZEltcG9ydEVudW1fLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkU3RyaW5nUGllY2VfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb21wdXRlU3RyaW5nU2l6ZU5vVGFnKHJlcGVhdGVkU3RyaW5nUGllY2VfLmdldFJhdyhpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUxpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZENvcmRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb21wdXRlU3RyaW5nU2l6ZU5vVGFnKHJlcGVhdGVkQ29yZF8uZ2V0UmF3KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZENvcmRMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRMYXp5TWVzc2FnZV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNTcsIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmdldChpKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDgwMDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSg2MSwgZGVmYXVsdEludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MTAwMDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDY0U2l6ZSg2MiwgZGVmYXVsdEludDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MjAwMDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZVVJbnQzMlNpemUoNjMsIGRlZmF1bHRVaW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHg0MDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlVUludDY0U2l6ZSg2NCwgZGVmYXVsdFVpbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDgwMDAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVTSW50MzJTaXplKDY1LCBkZWZhdWx0U2ludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZVNJbnQ2NFNpemUoNjYsIGRlZmF1bHRTaW50NjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRml4ZWQzMlNpemUoNjcsIGRlZmF1bHRGaXhlZDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUZpeGVkNjRTaXplKDY4LCBkZWZhdWx0Rml4ZWQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVTRml4ZWQzMlNpemUoNjksIGRlZmF1bHRTZml4ZWQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVTRml4ZWQ2NFNpemUoNzAsIGRlZmF1bHRTZml4ZWQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDIwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVGbG9hdFNpemUoNzEsIGRlZmF1bHRGbG9hdF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVEb3VibGVTaXplKDcyLCBkZWZhdWx0RG91YmxlXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUJvb2xTaXplKDczLCBkZWZhdWx0Qm9vbF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMTAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoNzQsIGRlZmF1bHRTdHJpbmdfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlQnl0ZXNTaXplKDc1LCBkZWZhdWx0Qnl0ZXNfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDQwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRW51bVNpemUoODEsIGRlZmF1bHROZXN0ZWRFbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUVudW1TaXplKDgyLCBkZWZhdWx0Rm9yZWlnbkVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRW51bVNpemUoODMsIGRlZmF1bHRJbXBvcnRFbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDIwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5jb21wdXRlU3RyaW5nU2l6ZSg4NCwgZGVmYXVsdFN0cmluZ1BpZWNlXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDQwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5jb21wdXRlU3RyaW5nU2l6ZSg4NSwgZGVmYXVsdENvcmRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVVSW50MzJTaXplKAogICAgICAgICAgICAgIDExMSwgKGludCkoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEyKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDExMiwgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5jb21wdXRlU3RyaW5nU2l6ZSgxMTMsIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNCkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemUoCiAgICAgICAgICAgICAgMTE0LCAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTE1LCAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDgwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxMTYsIGRlY2VwdGl2ZWx5TmFtZWRMaXN0Xyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTcpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTE3LCAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc09wdGlvbmFsSW50MzIoKSAhPSBvdGhlci5oYXNPcHRpb25hbEludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsSW50MzIoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbEludDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T3B0aW9uYWxJbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsSW50NjQoKSAhPSBvdGhlci5oYXNPcHRpb25hbEludDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsSW50NjQoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbEludDY0KCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T3B0aW9uYWxJbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsVWludDMyKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxVaW50MzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxVaW50MzIoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbFVpbnQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldE9wdGlvbmFsVWludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxVaW50NjQoKSAhPSBvdGhlci5oYXNPcHRpb25hbFVpbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbFVpbnQ2NCgpKSB7CiAgICAgICAgaWYgKGdldE9wdGlvbmFsVWludDY0KCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T3B0aW9uYWxVaW50NjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFNpbnQzMigpICE9IG90aGVyLmhhc09wdGlvbmFsU2ludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsU2ludDMyKCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxTaW50MzIoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRPcHRpb25hbFNpbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU2ludDY0KCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxTaW50NjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxTaW50NjQoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbFNpbnQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldE9wdGlvbmFsU2ludDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxGaXhlZDMyKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxGaXhlZDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsRml4ZWQzMigpKSB7CiAgICAgICAgaWYgKGdldE9wdGlvbmFsRml4ZWQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldE9wdGlvbmFsRml4ZWQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsRml4ZWQ2NCgpICE9IG90aGVyLmhhc09wdGlvbmFsRml4ZWQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEZpeGVkNjQoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbEZpeGVkNjQoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRPcHRpb25hbEZpeGVkNjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFNmaXhlZDMyKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxTZml4ZWQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbFNmaXhlZDMyKCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxTZml4ZWQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldE9wdGlvbmFsU2ZpeGVkMzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFNmaXhlZDY0KCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxTZml4ZWQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbFNmaXhlZDY0KCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxTZml4ZWQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldE9wdGlvbmFsU2ZpeGVkNjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEZsb2F0KCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxGbG9hdCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEZsb2F0KCkpIHsKICAgICAgICBpZiAoamF2YS5sYW5nLkZsb2F0LmZsb2F0VG9JbnRCaXRzKGdldE9wdGlvbmFsRmxvYXQoKSkKICAgICAgICAgICAgIT0gamF2YS5sYW5nLkZsb2F0LmZsb2F0VG9JbnRCaXRzKAogICAgICAgICAgICAgICAgb3RoZXIuZ2V0T3B0aW9uYWxGbG9hdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbERvdWJsZSgpICE9IG90aGVyLmhhc09wdGlvbmFsRG91YmxlKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsRG91YmxlKCkpIHsKICAgICAgICBpZiAoamF2YS5sYW5nLkRvdWJsZS5kb3VibGVUb0xvbmdCaXRzKGdldE9wdGlvbmFsRG91YmxlKCkpCiAgICAgICAgICAgICE9IGphdmEubGFuZy5Eb3VibGUuZG91YmxlVG9Mb25nQml0cygKICAgICAgICAgICAgICAgIG90aGVyLmdldE9wdGlvbmFsRG91YmxlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQm9vbCgpICE9IG90aGVyLmhhc09wdGlvbmFsQm9vbCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEJvb2woKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbEJvb2woKQogICAgICAgICAgICAhPSBvdGhlci5nZXRPcHRpb25hbEJvb2woKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFN0cmluZygpICE9IG90aGVyLmhhc09wdGlvbmFsU3RyaW5nKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsU3RyaW5nKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsU3RyaW5nKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbFN0cmluZygpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEJ5dGVzKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxCeXRlcygpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEJ5dGVzKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsQnl0ZXMoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsQnl0ZXMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cCgpICE9IG90aGVyLmhhc09wdGlvbmFsR3JvdXAoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cCgpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbEdyb3VwKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbEdyb3VwKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsTmVzdGVkTWVzc2FnZSgpICE9IG90aGVyLmhhc09wdGlvbmFsTmVzdGVkTWVzc2FnZSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpICE9IG90aGVyLmhhc09wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsSW1wb3J0TWVzc2FnZSgpICE9IG90aGVyLmhhc09wdGlvbmFsSW1wb3J0TWVzc2FnZSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxOZXN0ZWRFbnVtKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxOZXN0ZWRFbnVtKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsTmVzdGVkRW51bSgpKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkRW51bV8gIT0gb3RoZXIub3B0aW9uYWxOZXN0ZWRFbnVtXykgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEZvcmVpZ25FbnVtKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxGb3JlaWduRW51bSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEZvcmVpZ25FbnVtKCkpIHsKICAgICAgICBpZiAob3B0aW9uYWxGb3JlaWduRW51bV8gIT0gb3RoZXIub3B0aW9uYWxGb3JlaWduRW51bV8pIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxJbXBvcnRFbnVtKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxJbXBvcnRFbnVtKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsSW1wb3J0RW51bSgpKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsSW1wb3J0RW51bV8gIT0gb3RoZXIub3B0aW9uYWxJbXBvcnRFbnVtXykgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFN0cmluZ1BpZWNlKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxTdHJpbmdQaWVjZSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbFN0cmluZ1BpZWNlKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsU3RyaW5nUGllY2UoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsU3RyaW5nUGllY2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxDb3JkKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxDb3JkKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsQ29yZCgpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbENvcmQoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsQ29yZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSAhPSBvdGhlci5oYXNPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsTGF6eU1lc3NhZ2UoKSAhPSBvdGhlci5oYXNPcHRpb25hbExhenlNZXNzYWdlKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsTGF6eU1lc3NhZ2UoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpICE9IG90aGVyLmhhc09wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEludDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkSW50NjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRJbnQ2NExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZFVpbnQzMkxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZFVpbnQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZFVpbnQ2NExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZFVpbnQ2NExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZFNpbnQzMkxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZFNpbnQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZFNpbnQ2NExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZFNpbnQ2NExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkRml4ZWQ2NExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEZpeGVkNjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRTZml4ZWQzMkxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZFNmaXhlZDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkU2ZpeGVkNjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRTZml4ZWQ2NExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZEZsb2F0TGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkRmxvYXRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWREb3VibGVMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWREb3VibGVMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRCb29sTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkQm9vbExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZFN0cmluZ0xpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZFN0cmluZ0xpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZEJ5dGVzTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkQnl0ZXNMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRHcm91cExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEdyb3VwTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghcmVwZWF0ZWROZXN0ZWRFbnVtXy5lcXVhbHMob3RoZXIucmVwZWF0ZWROZXN0ZWRFbnVtXykpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFyZXBlYXRlZEZvcmVpZ25FbnVtXy5lcXVhbHMob3RoZXIucmVwZWF0ZWRGb3JlaWduRW51bV8pKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghcmVwZWF0ZWRJbXBvcnRFbnVtXy5lcXVhbHMob3RoZXIucmVwZWF0ZWRJbXBvcnRFbnVtXykpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZFN0cmluZ1BpZWNlTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkU3RyaW5nUGllY2VMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRDb3JkTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkQ29yZExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZExhenlNZXNzYWdlTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkTGF6eU1lc3NhZ2VMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0SW50MzIoKSAhPSBvdGhlci5oYXNEZWZhdWx0SW50MzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdEludDMyKCkpIHsKICAgICAgICBpZiAoZ2V0RGVmYXVsdEludDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVmYXVsdEludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEludDY0KCkgIT0gb3RoZXIuaGFzRGVmYXVsdEludDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRJbnQ2NCgpKSB7CiAgICAgICAgaWYgKGdldERlZmF1bHRJbnQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRJbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRVaW50MzIoKSAhPSBvdGhlci5oYXNEZWZhdWx0VWludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRVaW50MzIoKSkgewogICAgICAgIGlmIChnZXREZWZhdWx0VWludDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVmYXVsdFVpbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRVaW50NjQoKSAhPSBvdGhlci5oYXNEZWZhdWx0VWludDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRVaW50NjQoKSkgewogICAgICAgIGlmIChnZXREZWZhdWx0VWludDY0KCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVmYXVsdFVpbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTaW50MzIoKSAhPSBvdGhlci5oYXNEZWZhdWx0U2ludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRTaW50MzIoKSkgewogICAgICAgIGlmIChnZXREZWZhdWx0U2ludDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVmYXVsdFNpbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTaW50NjQoKSAhPSBvdGhlci5oYXNEZWZhdWx0U2ludDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRTaW50NjQoKSkgewogICAgICAgIGlmIChnZXREZWZhdWx0U2ludDY0KCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVmYXVsdFNpbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRGaXhlZDMyKCkgIT0gb3RoZXIuaGFzRGVmYXVsdEZpeGVkMzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdEZpeGVkMzIoKSkgewogICAgICAgIGlmIChnZXREZWZhdWx0Rml4ZWQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRGaXhlZDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEZpeGVkNjQoKSAhPSBvdGhlci5oYXNEZWZhdWx0Rml4ZWQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0Rml4ZWQ2NCgpKSB7CiAgICAgICAgaWYgKGdldERlZmF1bHRGaXhlZDY0KCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVmYXVsdEZpeGVkNjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U2ZpeGVkMzIoKSAhPSBvdGhlci5oYXNEZWZhdWx0U2ZpeGVkMzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdFNmaXhlZDMyKCkpIHsKICAgICAgICBpZiAoZ2V0RGVmYXVsdFNmaXhlZDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVmYXVsdFNmaXhlZDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdFNmaXhlZDY0KCkgIT0gb3RoZXIuaGFzRGVmYXVsdFNmaXhlZDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRTZml4ZWQ2NCgpKSB7CiAgICAgICAgaWYgKGdldERlZmF1bHRTZml4ZWQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRTZml4ZWQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRGbG9hdCgpICE9IG90aGVyLmhhc0RlZmF1bHRGbG9hdCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0RmxvYXQoKSkgewogICAgICAgIGlmIChqYXZhLmxhbmcuRmxvYXQuZmxvYXRUb0ludEJpdHMoZ2V0RGVmYXVsdEZsb2F0KCkpCiAgICAgICAgICAgICE9IGphdmEubGFuZy5GbG9hdC5mbG9hdFRvSW50Qml0cygKICAgICAgICAgICAgICAgIG90aGVyLmdldERlZmF1bHRGbG9hdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0RG91YmxlKCkgIT0gb3RoZXIuaGFzRGVmYXVsdERvdWJsZSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0RG91YmxlKCkpIHsKICAgICAgICBpZiAoamF2YS5sYW5nLkRvdWJsZS5kb3VibGVUb0xvbmdCaXRzKGdldERlZmF1bHREb3VibGUoKSkKICAgICAgICAgICAgIT0gamF2YS5sYW5nLkRvdWJsZS5kb3VibGVUb0xvbmdCaXRzKAogICAgICAgICAgICAgICAgb3RoZXIuZ2V0RGVmYXVsdERvdWJsZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Qm9vbCgpICE9IG90aGVyLmhhc0RlZmF1bHRCb29sKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRCb29sKCkpIHsKICAgICAgICBpZiAoZ2V0RGVmYXVsdEJvb2woKQogICAgICAgICAgICAhPSBvdGhlci5nZXREZWZhdWx0Qm9vbCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTdHJpbmcoKSAhPSBvdGhlci5oYXNEZWZhdWx0U3RyaW5nKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRTdHJpbmcoKSkgewogICAgICAgIGlmICghZ2V0RGVmYXVsdFN0cmluZygpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RGVmYXVsdFN0cmluZygpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Qnl0ZXMoKSAhPSBvdGhlci5oYXNEZWZhdWx0Qnl0ZXMoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdEJ5dGVzKCkpIHsKICAgICAgICBpZiAoIWdldERlZmF1bHRCeXRlcygpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RGVmYXVsdEJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHROZXN0ZWRFbnVtKCkgIT0gb3RoZXIuaGFzRGVmYXVsdE5lc3RlZEVudW0oKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdE5lc3RlZEVudW0oKSkgewogICAgICAgIGlmIChkZWZhdWx0TmVzdGVkRW51bV8gIT0gb3RoZXIuZGVmYXVsdE5lc3RlZEVudW1fKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRGb3JlaWduRW51bSgpICE9IG90aGVyLmhhc0RlZmF1bHRGb3JlaWduRW51bSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0Rm9yZWlnbkVudW0oKSkgewogICAgICAgIGlmIChkZWZhdWx0Rm9yZWlnbkVudW1fICE9IG90aGVyLmRlZmF1bHRGb3JlaWduRW51bV8pIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEltcG9ydEVudW0oKSAhPSBvdGhlci5oYXNEZWZhdWx0SW1wb3J0RW51bSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0SW1wb3J0RW51bSgpKSB7CiAgICAgICAgaWYgKGRlZmF1bHRJbXBvcnRFbnVtXyAhPSBvdGhlci5kZWZhdWx0SW1wb3J0RW51bV8pIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdFN0cmluZ1BpZWNlKCkgIT0gb3RoZXIuaGFzRGVmYXVsdFN0cmluZ1BpZWNlKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRTdHJpbmdQaWVjZSgpKSB7CiAgICAgICAgaWYgKCFnZXREZWZhdWx0U3RyaW5nUGllY2UoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldERlZmF1bHRTdHJpbmdQaWVjZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Q29yZCgpICE9IG90aGVyLmhhc0RlZmF1bHRDb3JkKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRDb3JkKCkpIHsKICAgICAgICBpZiAoIWdldERlZmF1bHRDb3JkKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXREZWZhdWx0Q29yZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWNlcHRpdmVseU5hbWVkTGlzdCgpICE9IG90aGVyLmhhc0RlY2VwdGl2ZWx5TmFtZWRMaXN0KCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlY2VwdGl2ZWx5TmFtZWRMaXN0KCkpIHsKICAgICAgICBpZiAoZ2V0RGVjZXB0aXZlbHlOYW1lZExpc3QoKQogICAgICAgICAgICAhPSBvdGhlci5nZXREZWNlcHRpdmVseU5hbWVkTGlzdCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFnZXRPbmVvZkZpZWxkQ2FzZSgpLmVxdWFscyhvdGhlci5nZXRPbmVvZkZpZWxkQ2FzZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBzd2l0Y2ggKG9uZW9mRmllbGRDYXNlXykgewogICAgICAgIGNhc2UgMTExOgogICAgICAgICAgaWYgKGdldE9uZW9mVWludDMyKCkKICAgICAgICAgICAgICAhPSBvdGhlci5nZXRPbmVvZlVpbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDExMjoKICAgICAgICAgIGlmICghZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mTmVzdGVkTWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMTM6CiAgICAgICAgICBpZiAoIWdldE9uZW9mU3RyaW5nKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mU3RyaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDExNDoKICAgICAgICAgIGlmICghZ2V0T25lb2ZCeXRlcygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZkJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDExNToKICAgICAgICAgIGlmICghZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZSgpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDExNzoKICAgICAgICAgIGlmICghZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlMigpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZk5lc3RlZE1lc3NhZ2UyKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDA6CiAgICAgICAgZGVmYXVsdDoKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNPcHRpb25hbEludDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxJbnQzMigpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEludDY0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9JTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgZ2V0T3B0aW9uYWxJbnQ2NCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxVaW50MzIoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX1VJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxVaW50MzIoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxVaW50NjQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX1VJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgZ2V0T3B0aW9uYWxVaW50NjQoKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU2ludDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9TSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsU2ludDMyKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU2ludDY0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9TSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGdldE9wdGlvbmFsU2ludDY0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEZpeGVkMzIoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsRml4ZWQzMigpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEZpeGVkNjQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGdldE9wdGlvbmFsRml4ZWQ2NCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxTZml4ZWQzMigpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfU0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsU2ZpeGVkMzIoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxTZml4ZWQ2NCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfU0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGdldE9wdGlvbmFsU2ZpeGVkNjQoKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsRmxvYXQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0ZMT0FUX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBqYXZhLmxhbmcuRmxvYXQuZmxvYXRUb0ludEJpdHMoCiAgICAgICAgICAgIGdldE9wdGlvbmFsRmxvYXQoKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsRG91YmxlKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9ET1VCTEVfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGphdmEubGFuZy5Eb3VibGUuZG91YmxlVG9Mb25nQml0cyhnZXRPcHRpb25hbERvdWJsZSgpKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQm9vbCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfQk9PTF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoQm9vbGVhbigKICAgICAgICAgICAgZ2V0T3B0aW9uYWxCb29sKCkpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFN0cmluZygpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfU1RSSU5HX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbFN0cmluZygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQnl0ZXMoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0JZVEVTX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbEJ5dGVzKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxHUk9VUF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxHcm91cCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsTmVzdGVkTWVzc2FnZSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfTkVTVEVEX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0ZPUkVJR05fTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsSW1wb3J0TWVzc2FnZSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfSU1QT1JUX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsTmVzdGVkRW51bSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfTkVTVEVEX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIG9wdGlvbmFsTmVzdGVkRW51bV87CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsRm9yZWlnbkVudW0oKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0ZPUkVJR05fRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgb3B0aW9uYWxGb3JlaWduRW51bV87CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsSW1wb3J0RW51bSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfSU1QT1JUX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIG9wdGlvbmFsSW1wb3J0RW51bV87CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU3RyaW5nUGllY2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX1NUUklOR19QSUVDRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxTdHJpbmdQaWVjZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQ29yZCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfQ09SRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxDb3JkKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9QVUJMSUNfSU1QT1JUX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsTGF6eU1lc3NhZ2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0xBWllfTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9VTlZFUklGSUVEX0xBWllfTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEludDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEludDY0Q291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9JTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRJbnQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZFVpbnQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfVUlOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZFVpbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZFVpbnQ2NENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfVUlOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZFVpbnQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZFNpbnQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfU0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZFNpbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZFNpbnQ2NENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfU0lOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZFNpbnQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEZpeGVkNjRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkRml4ZWQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZFNmaXhlZDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9TRklYRUQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRTZml4ZWQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZFNmaXhlZDY0Q291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9TRklYRUQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRTZml4ZWQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEZsb2F0Q291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9GTE9BVF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRGbG9hdExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZERvdWJsZUNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfRE9VQkxFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZERvdWJsZUxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEJvb2xDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0JPT0xfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkQm9vbExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZFN0cmluZ0NvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfU1RSSU5HX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZFN0cmluZ0xpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEJ5dGVzQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9CWVRFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRCeXRlc0xpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEdyb3VwQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFREdST1VQX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZEdyb3VwTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfTkVTVEVEX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9GT1JFSUdOX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9JTVBPUlRfTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGdldFJlcGVhdGVkTmVzdGVkRW51bUNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfTkVTVEVEX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIHJlcGVhdGVkTmVzdGVkRW51bV8uaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRGb3JlaWduRW51bUNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfRk9SRUlHTl9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyByZXBlYXRlZEZvcmVpZ25FbnVtXy5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEltcG9ydEVudW1Db3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0lNUE9SVF9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyByZXBlYXRlZEltcG9ydEVudW1fLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGdldFJlcGVhdGVkU3RyaW5nUGllY2VDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX1NUUklOR19QSUVDRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZENvcmRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0NPUkRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkQ29yZExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZExhenlNZXNzYWdlQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9MQVpZX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEludDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZWZhdWx0SW50MzIoKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEludDY0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0lOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmhhc2hMb25nKAogICAgICAgICAgICBnZXREZWZhdWx0SW50NjQoKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRVaW50MzIoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfVUlOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZWZhdWx0VWludDMyKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRVaW50NjQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfVUlOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmhhc2hMb25nKAogICAgICAgICAgICBnZXREZWZhdWx0VWludDY0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U2ludDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX1NJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RGVmYXVsdFNpbnQzMigpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U2ludDY0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX1NJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgZ2V0RGVmYXVsdFNpbnQ2NCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEZpeGVkMzIoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfRklYRUQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RGVmYXVsdEZpeGVkMzIoKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEZpeGVkNjQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfRklYRUQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgZ2V0RGVmYXVsdEZpeGVkNjQoKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTZml4ZWQzMigpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9TRklYRUQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RGVmYXVsdFNmaXhlZDMyKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTZml4ZWQ2NCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9TRklYRUQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgZ2V0RGVmYXVsdFNmaXhlZDY0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0RmxvYXQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfRkxPQVRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGphdmEubGFuZy5GbG9hdC5mbG9hdFRvSW50Qml0cygKICAgICAgICAgICAgZ2V0RGVmYXVsdEZsb2F0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0RG91YmxlKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0RPVUJMRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgamF2YS5sYW5nLkRvdWJsZS5kb3VibGVUb0xvbmdCaXRzKGdldERlZmF1bHREb3VibGUoKSkpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Qm9vbCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9CT09MX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmhhc2hCb29sZWFuKAogICAgICAgICAgICBnZXREZWZhdWx0Qm9vbCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdFN0cmluZygpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9TVFJJTkdfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlZmF1bHRTdHJpbmcoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Qnl0ZXMoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfQllURVNfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlZmF1bHRCeXRlcygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHROZXN0ZWRFbnVtKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX05FU1RFRF9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBkZWZhdWx0TmVzdGVkRW51bV87CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRGb3JlaWduRW51bSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9GT1JFSUdOX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGRlZmF1bHRGb3JlaWduRW51bV87CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRJbXBvcnRFbnVtKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0lNUE9SVF9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBkZWZhdWx0SW1wb3J0RW51bV87CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTdHJpbmdQaWVjZSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlZmF1bHRTdHJpbmdQaWVjZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRDb3JkKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0NPUkRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlZmF1bHRDb3JkKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVjZXB0aXZlbHlOYW1lZExpc3QoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFQ0VQVElWRUxZX05BTUVEX0xJU1RfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlY2VwdGl2ZWx5TmFtZWRMaXN0KCk7CiAgICAgIH0KICAgICAgc3dpdGNoIChvbmVvZkZpZWxkQ2FzZV8pIHsKICAgICAgICBjYXNlIDExMToKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX1VJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZlVpbnQzMigpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMTI6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9ORVNURURfTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZk5lc3RlZE1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMTM6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9TVFJJTkdfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZTdHJpbmcoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMTQ6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9CWVRFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZkJ5dGVzKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTE1OgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfTEFaWV9ORVNURURfTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTE3OgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfTkVTVEVEX01FU1NBR0UyX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9uZW9mTmVzdGVkTWVzc2FnZTIoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAwOgogICAgICAgIGRlZmF1bHQ6CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogU2FtZSBhcyBUZXN0QWxsVHlwZXMgYnV0IHdpdGggdGhlIGxpdGUgcnVudGltZS4KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCkgewogICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMpIHsKICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZUZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRSZXBlYXRlZEdyb3VwRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgYml0RmllbGQxXyA9IDA7CiAgICAgICAgYml0RmllbGQyXyA9IDA7CiAgICAgICAgb3B0aW9uYWxJbnQzMl8gPSAwOwogICAgICAgIG9wdGlvbmFsSW50NjRfID0gMEw7CiAgICAgICAgb3B0aW9uYWxVaW50MzJfID0gMDsKICAgICAgICBvcHRpb25hbFVpbnQ2NF8gPSAwTDsKICAgICAgICBvcHRpb25hbFNpbnQzMl8gPSAwOwogICAgICAgIG9wdGlvbmFsU2ludDY0XyA9IDBMOwogICAgICAgIG9wdGlvbmFsRml4ZWQzMl8gPSAwOwogICAgICAgIG9wdGlvbmFsRml4ZWQ2NF8gPSAwTDsKICAgICAgICBvcHRpb25hbFNmaXhlZDMyXyA9IDA7CiAgICAgICAgb3B0aW9uYWxTZml4ZWQ2NF8gPSAwTDsKICAgICAgICBvcHRpb25hbEZsb2F0XyA9IDBGOwogICAgICAgIG9wdGlvbmFsRG91YmxlXyA9IDBEOwogICAgICAgIG9wdGlvbmFsQm9vbF8gPSBmYWxzZTsKICAgICAgICBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgICAgICBvcHRpb25hbEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgICBvcHRpb25hbEdyb3VwXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9wdGlvbmFsTmVzdGVkRW51bV8gPSAxOwogICAgICAgIG9wdGlvbmFsRm9yZWlnbkVudW1fID0gNDsKICAgICAgICBvcHRpb25hbEltcG9ydEVudW1fID0gNzsKICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9ICIiOwogICAgICAgIG9wdGlvbmFsQ29yZF8gPSAiIjsKICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXBlYXRlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHJlcGVhdGVkSW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIHJlcGVhdGVkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHJlcGVhdGVkVWludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICByZXBlYXRlZFNpbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICByZXBlYXRlZFNpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICByZXBlYXRlZFNmaXhlZDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICByZXBlYXRlZEZsb2F0XyA9IGVtcHR5RmxvYXRMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRCb29sXyA9IGVtcHR5Qm9vbGVhbkxpc3QoKTsKICAgICAgICByZXBlYXRlZFN0cmluZ18gPQogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRCeXRlc18gPSBlbXB0eUxpc3QoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNsYXNzKTsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IG51bGw7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDA0MDApOwogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAwODAwKTsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IG51bGw7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDEwMDApOwogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDA0MDAwKTsKICAgICAgICByZXBlYXRlZEZvcmVpZ25FbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwODAwMCk7CiAgICAgICAgcmVwZWF0ZWRJbXBvcnRFbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAxMDAwMCk7CiAgICAgICAgcmVwZWF0ZWRTdHJpbmdQaWVjZV8gPQogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRDb3JkXyA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdC5lbXB0eUxpc3QoKTsKICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwODAwMDApOwogICAgICAgIGRlZmF1bHRJbnQzMl8gPSA0MTsKICAgICAgICBkZWZhdWx0SW50NjRfID0gNDJMOwogICAgICAgIGRlZmF1bHRVaW50MzJfID0gNDM7CiAgICAgICAgZGVmYXVsdFVpbnQ2NF8gPSA0NEw7CiAgICAgICAgZGVmYXVsdFNpbnQzMl8gPSAtNDU7CiAgICAgICAgZGVmYXVsdFNpbnQ2NF8gPSA0Nkw7CiAgICAgICAgZGVmYXVsdEZpeGVkMzJfID0gNDc7CiAgICAgICAgZGVmYXVsdEZpeGVkNjRfID0gNDhMOwogICAgICAgIGRlZmF1bHRTZml4ZWQzMl8gPSA0OTsKICAgICAgICBkZWZhdWx0U2ZpeGVkNjRfID0gLTUwTDsKICAgICAgICBkZWZhdWx0RmxvYXRfID0gNTEuNUY7CiAgICAgICAgZGVmYXVsdERvdWJsZV8gPSA1MjAwMEQ7CiAgICAgICAgZGVmYXVsdEJvb2xfID0gdHJ1ZTsKICAgICAgICBkZWZhdWx0U3RyaW5nXyA9ICJoZWxsbyI7CiAgICAgICAgZGVmYXVsdEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoIndvcmxkIik7CiAgICAgICAgZGVmYXVsdE5lc3RlZEVudW1fID0gMjsKICAgICAgICBkZWZhdWx0Rm9yZWlnbkVudW1fID0gNTsKICAgICAgICBkZWZhdWx0SW1wb3J0RW51bV8gPSA4OwogICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSAiYWJjIjsKICAgICAgICBkZWZhdWx0Q29yZF8gPSAiMTIzIjsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgZGVjZXB0aXZlbHlOYW1lZExpc3RfID0gMDsKICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSh0aGlzKTsKICAgICAgICBidWlsZFBhcnRpYWxSZXBlYXRlZEZpZWxkcyhyZXN1bHQpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgaWYgKGJpdEZpZWxkMV8gIT0gMCkgeyBidWlsZFBhcnRpYWwxKHJlc3VsdCk7IH0KICAgICAgICBpZiAoYml0RmllbGQyXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDIocmVzdWx0KTsgfQogICAgICAgIGJ1aWxkUGFydGlhbE9uZW9mcyhyZXN1bHQpOwogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsUmVwZWF0ZWRGaWVsZHMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXN1bHQpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwNDAwKSAhPSAwKSkgewogICAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDA0MDApOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkR3JvdXBfID0gcmVwZWF0ZWRHcm91cF87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEdyb3VwXyA9IHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VfKTsKICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDA4MDApOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkTmVzdGVkTWVzc2FnZV8gPSByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyA9IHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDEwMDApICE9IDApKSB7CiAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8pOwogICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMTAwMCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8gPSByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfID0gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8pOwogICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMjAwMCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyA9IHJlcGVhdGVkSW1wb3J0TWVzc2FnZV87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDQwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWROZXN0ZWRFbnVtXyk7CiAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwNDAwMCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5yZXBlYXRlZE5lc3RlZEVudW1fID0gcmVwZWF0ZWROZXN0ZWRFbnVtXzsKICAgICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwODAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbkVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRGb3JlaWduRW51bV8pOwogICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDgwMDApOwogICAgICAgIH0KICAgICAgICByZXN1bHQucmVwZWF0ZWRGb3JlaWduRW51bV8gPSByZXBlYXRlZEZvcmVpZ25FbnVtXzsKICAgICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAxMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0RW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZEltcG9ydEVudW1fKTsKICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDEwMDAwKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnJlcGVhdGVkSW1wb3J0RW51bV8gPSByZXBlYXRlZEltcG9ydEVudW1fOwogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwODAwMDApICE9IDApKSB7CiAgICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRMYXp5TWVzc2FnZV8pOwogICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDA4MDAwMCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRMYXp5TWVzc2FnZV8gPSByZXBlYXRlZExhenlNZXNzYWdlXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsSW50MzJfID0gb3B0aW9uYWxJbnQzMl87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxJbnQ2NF8gPSBvcHRpb25hbEludDY0XzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbFVpbnQzMl8gPSBvcHRpb25hbFVpbnQzMl87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxVaW50NjRfID0gb3B0aW9uYWxVaW50NjRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsU2ludDMyXyA9IG9wdGlvbmFsU2ludDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbFNpbnQ2NF8gPSBvcHRpb25hbFNpbnQ2NF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwNDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxGaXhlZDMyXyA9IG9wdGlvbmFsRml4ZWQzMl87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxGaXhlZDY0XyA9IG9wdGlvbmFsRml4ZWQ2NF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAxMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxTZml4ZWQzMl8gPSBvcHRpb25hbFNmaXhlZDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbFNmaXhlZDY0XyA9IG9wdGlvbmFsU2ZpeGVkNjRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwNDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsRmxvYXRfID0gb3B0aW9uYWxGbG9hdF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxEb3VibGVfID0gb3B0aW9uYWxEb3VibGVfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAxMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsQm9vbF8gPSBvcHRpb25hbEJvb2xfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAyMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsU3RyaW5nXyA9IG9wdGlvbmFsU3RyaW5nXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwNDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEJ5dGVzXyA9IG9wdGlvbmFsQnl0ZXNfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDA4MDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsR3JvdXBfID0gb3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsR3JvdXBfCiAgICAgICAgICAgICAgOiBvcHRpb25hbEdyb3VwQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAxMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbE5lc3RlZE1lc3NhZ2VfID0gb3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXwogICAgICAgICAgICAgIDogb3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAyMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEZvcmVpZ25NZXNzYWdlXyA9IG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgPyBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXwogICAgICAgICAgICAgIDogb3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwNDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxJbXBvcnRNZXNzYWdlXyA9IG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8KICAgICAgICAgICAgICA6IG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwNDAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwODAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxOZXN0ZWRFbnVtXyA9IG9wdGlvbmFsTmVzdGVkRW51bV87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwODAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAxMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxGb3JlaWduRW51bV8gPSBvcHRpb25hbEZvcmVpZ25FbnVtXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDEwMDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDIwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEltcG9ydEVudW1fID0gb3B0aW9uYWxJbXBvcnRFbnVtXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDIwMDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDQwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbFN0cmluZ1BpZWNlXyA9IG9wdGlvbmFsU3RyaW5nUGllY2VfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwNDAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwODAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsQ29yZF8gPSBvcHRpb25hbENvcmRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwODAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAxMDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgPyBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfCiAgICAgICAgICAgICAgOiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAxMDAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAyMDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsTGF6eU1lc3NhZ2VfID0gb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsTGF6eU1lc3NhZ2VfCiAgICAgICAgICAgICAgOiBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMjAwMDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwNDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZV8gPSBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXwogICAgICAgICAgICAgIDogb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDA0MDAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDA4MDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkSW50MzJfID0gcmVwZWF0ZWRJbnQzMl87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MTAwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRJbnQ2NF8gPSByZXBlYXRlZEludDY0XzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgyMDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkVWludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRVaW50MzJfID0gcmVwZWF0ZWRVaW50MzJfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDQwMDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRVaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZFVpbnQ2NF8gPSByZXBlYXRlZFVpbnQ2NF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4ODAwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZFNpbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkU2ludDMyXyA9IHJlcGVhdGVkU2ludDMyXzsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDEoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDFfID0gYml0RmllbGQxXzsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRTaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZFNpbnQ2NF8gPSByZXBlYXRlZFNpbnQ2NF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEZpeGVkMzJfID0gcmVwZWF0ZWRGaXhlZDMyXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkRml4ZWQ2NF8gPSByZXBlYXRlZEZpeGVkNjRfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRTZml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkU2ZpeGVkMzJfID0gcmVwZWF0ZWRTZml4ZWQzMl87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZFNmaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRTZml4ZWQ2NF8gPSByZXBlYXRlZFNmaXhlZDY0XzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkRmxvYXRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEZsb2F0XyA9IHJlcGVhdGVkRmxvYXRfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWREb3VibGVfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZERvdWJsZV8gPSByZXBlYXRlZERvdWJsZV87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEJvb2xfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEJvb2xfID0gcmVwZWF0ZWRCb29sXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkU3RyaW5nXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRTdHJpbmdfID0gcmVwZWF0ZWRTdHJpbmdfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMDAwMjAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRCeXRlc18ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkQnl0ZXNfID0gcmVwZWF0ZWRCeXRlc187CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDAwMjAwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZFN0cmluZ1BpZWNlXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRTdHJpbmdQaWVjZV8gPSByZXBlYXRlZFN0cmluZ1BpZWNlXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDA0MDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkQ29yZF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkQ29yZF8gPSByZXBlYXRlZENvcmRfOwogICAgICAgIH0KICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDEwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0SW50MzJfID0gZGVmYXVsdEludDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwODAwMDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDIwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0SW50NjRfID0gZGVmYXVsdEludDY0XzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgxMDAwMDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDQwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0VWludDMyXyA9IGRlZmF1bHRVaW50MzJfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDIwMDAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwODAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRVaW50NjRfID0gZGVmYXVsdFVpbnQ2NF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4NDAwMDAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDEwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdFNpbnQzMl8gPSBkZWZhdWx0U2ludDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHg4MDAwMDAwMDsKICAgICAgICB9CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMV8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDIwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdFNpbnQ2NF8gPSBkZWZhdWx0U2ludDY0XzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwNDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0Rml4ZWQzMl8gPSBkZWZhdWx0Rml4ZWQzMl87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDgwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdEZpeGVkNjRfID0gZGVmYXVsdEZpeGVkNjRfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAwMDA0OwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDEwMDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRTZml4ZWQzMl8gPSBkZWZhdWx0U2ZpeGVkMzJfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAwMDA4OwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDIwMDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRTZml4ZWQ2NF8gPSBkZWZhdWx0U2ZpeGVkNjRfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAwMDEwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDQwMDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRGbG9hdF8gPSBkZWZhdWx0RmxvYXRfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAwMDIwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDgwMDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHREb3VibGVfID0gZGVmYXVsdERvdWJsZV87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMV8gfD0gdG9fYml0RmllbGQxXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDJfID0gYml0RmllbGQyXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQxXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDJfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0Qm9vbF8gPSBkZWZhdWx0Qm9vbF87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQyXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdFN0cmluZ18gPSBkZWZhdWx0U3RyaW5nXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwMDEwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDJfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0Qnl0ZXNfID0gZGVmYXVsdEJ5dGVzXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwMDIwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDJfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0TmVzdGVkRW51bV8gPSBkZWZhdWx0TmVzdGVkRW51bV87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQyXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdEZvcmVpZ25FbnVtXyA9IGRlZmF1bHRGb3JlaWduRW51bV87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQyXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdEltcG9ydEVudW1fID0gZGVmYXVsdEltcG9ydEVudW1fOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAxMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMl8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRTdHJpbmdQaWVjZV8gPSBkZWZhdWx0U3RyaW5nUGllY2VfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAyMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMl8gJiAweDAwMDAwMDgwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRDb3JkXyA9IGRlZmF1bHRDb3JkXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwNDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDJfICYgMHgwMDAwNDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWNlcHRpdmVseU5hbWVkTGlzdF8gPSBkZWNlcHRpdmVseU5hbWVkTGlzdF87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDFfIHw9IHRvX2JpdEZpZWxkMV87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWxPbmVvZnMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXN1bHQpIHsKICAgICAgICByZXN1bHQub25lb2ZGaWVsZENhc2VfID0gb25lb2ZGaWVsZENhc2VfOwogICAgICAgIHJlc3VsdC5vbmVvZkZpZWxkXyA9IHRoaXMub25lb2ZGaWVsZF87CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIgJiYKICAgICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRfID0gb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUgJiYKICAgICAgICAgICAgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJlc3VsdC5vbmVvZkZpZWxkXyA9IG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNyAmJgogICAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRfID0gb25lb2ZOZXN0ZWRNZXNzYWdlMkJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEludDMyKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsSW50MzIob3RoZXIuZ2V0T3B0aW9uYWxJbnQzMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsSW50NjQoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxJbnQ2NChvdGhlci5nZXRPcHRpb25hbEludDY0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxVaW50MzIoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxVaW50MzIob3RoZXIuZ2V0T3B0aW9uYWxVaW50MzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbFVpbnQ2NCgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbFVpbnQ2NChvdGhlci5nZXRPcHRpb25hbFVpbnQ2NCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsU2ludDMyKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsU2ludDMyKG90aGVyLmdldE9wdGlvbmFsU2ludDMyKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxTaW50NjQoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxTaW50NjQob3RoZXIuZ2V0T3B0aW9uYWxTaW50NjQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEZpeGVkMzIoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxGaXhlZDMyKG90aGVyLmdldE9wdGlvbmFsRml4ZWQzMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsRml4ZWQ2NCgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEZpeGVkNjQob3RoZXIuZ2V0T3B0aW9uYWxGaXhlZDY0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxTZml4ZWQzMigpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbFNmaXhlZDMyKG90aGVyLmdldE9wdGlvbmFsU2ZpeGVkMzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbFNmaXhlZDY0KCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsU2ZpeGVkNjQob3RoZXIuZ2V0T3B0aW9uYWxTZml4ZWQ2NCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsRmxvYXQoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxGbG9hdChvdGhlci5nZXRPcHRpb25hbEZsb2F0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxEb3VibGUoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxEb3VibGUob3RoZXIuZ2V0T3B0aW9uYWxEb3VibGUoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEJvb2woKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxCb29sKG90aGVyLmdldE9wdGlvbmFsQm9vbCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsU3RyaW5nKCkpIHsKICAgICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IG90aGVyLm9wdGlvbmFsU3RyaW5nXzsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxCeXRlcygpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEJ5dGVzKG90aGVyLmdldE9wdGlvbmFsQnl0ZXMoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEdyb3VwKCkpIHsKICAgICAgICAgIG1lcmdlT3B0aW9uYWxHcm91cChvdGhlci5nZXRPcHRpb25hbEdyb3VwKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkpIHsKICAgICAgICAgIG1lcmdlT3B0aW9uYWxOZXN0ZWRNZXNzYWdlKG90aGVyLmdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbEZvcmVpZ25NZXNzYWdlKG90aGVyLmdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbEltcG9ydE1lc3NhZ2Uob3RoZXIuZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxOZXN0ZWRFbnVtKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsTmVzdGVkRW51bShvdGhlci5nZXRPcHRpb25hbE5lc3RlZEVudW0oKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEZvcmVpZ25FbnVtKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsRm9yZWlnbkVudW0ob3RoZXIuZ2V0T3B0aW9uYWxGb3JlaWduRW51bSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsSW1wb3J0RW51bSgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEltcG9ydEVudW0ob3RoZXIuZ2V0T3B0aW9uYWxJbXBvcnRFbnVtKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxTdHJpbmdQaWVjZSgpKSB7CiAgICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9IG90aGVyLm9wdGlvbmFsU3RyaW5nUGllY2VfOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwNDAwMDAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbENvcmQoKSkgewogICAgICAgICAgb3B0aW9uYWxDb3JkXyA9IG90aGVyLm9wdGlvbmFsQ29yZF87CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDA4MDAwMDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpKSB7CiAgICAgICAgICBtZXJnZU9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZShvdGhlci5nZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbExhenlNZXNzYWdlKCkpIHsKICAgICAgICAgIG1lcmdlT3B0aW9uYWxMYXp5TWVzc2FnZShvdGhlci5nZXRPcHRpb25hbExhenlNZXNzYWdlKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZShvdGhlci5nZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBvdGhlci5yZXBlYXRlZEludDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDgwMDAwMDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZEludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEludDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEludDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQ2NF8gPSBvdGhlci5yZXBlYXRlZEludDY0XzsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MTAwMDAwMDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkSW50NjRfLmFkZEFsbChvdGhlci5yZXBlYXRlZEludDY0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZFVpbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRVaW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZFVpbnQzMl8gPSBvdGhlci5yZXBlYXRlZFVpbnQzMl87CiAgICAgICAgICAgIHJlcGVhdGVkVWludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgyMDAwMDAwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkVWludDMyXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRVaW50MzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkVWludDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZFVpbnQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkVWludDY0XyA9IG90aGVyLnJlcGVhdGVkVWludDY0XzsKICAgICAgICAgICAgcmVwZWF0ZWRVaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDQwMDAwMDAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRVaW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRVaW50NjRfLmFkZEFsbChvdGhlci5yZXBlYXRlZFVpbnQ2NF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRTaW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkU2ludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRTaW50MzJfID0gb3RoZXIucmVwZWF0ZWRTaW50MzJfOwogICAgICAgICAgICByZXBlYXRlZFNpbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4ODAwMDAwMDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFNpbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZFNpbnQzMl8uYWRkQWxsKG90aGVyLnJlcGVhdGVkU2ludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZFNpbnQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRTaW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZFNpbnQ2NF8gPSBvdGhlci5yZXBlYXRlZFNpbnQ2NF87CiAgICAgICAgICAgIHJlcGVhdGVkU2ludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU2ludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkU2ludDY0Xy5hZGRBbGwob3RoZXIucmVwZWF0ZWRTaW50NjRfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkRml4ZWQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRGaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IG90aGVyLnJlcGVhdGVkRml4ZWQzMl87CiAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRGaXhlZDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEZpeGVkNjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkRml4ZWQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8gPSBvdGhlci5yZXBlYXRlZEZpeGVkNjRfOwogICAgICAgICAgICByZXBlYXRlZEZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8uYWRkQWxsKG90aGVyLnJlcGVhdGVkRml4ZWQ2NF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRTZml4ZWQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRTZml4ZWQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkMzJfID0gb3RoZXIucmVwZWF0ZWRTZml4ZWQzMl87CiAgICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDA4OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTZml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZFNmaXhlZDMyXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRTZml4ZWQzMl8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRTZml4ZWQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRTZml4ZWQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkNjRfID0gb3RoZXIucmVwZWF0ZWRTZml4ZWQ2NF87CiAgICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDEwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTZml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZFNmaXhlZDY0Xy5hZGRBbGwob3RoZXIucmVwZWF0ZWRTZml4ZWQ2NF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRGbG9hdF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRGbG9hdF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkRmxvYXRfID0gb3RoZXIucmVwZWF0ZWRGbG9hdF87CiAgICAgICAgICAgIHJlcGVhdGVkRmxvYXRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDIwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGbG9hdElzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZEZsb2F0Xy5hZGRBbGwob3RoZXIucmVwZWF0ZWRGbG9hdF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWREb3VibGVfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkRG91YmxlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWREb3VibGVfID0gb3RoZXIucmVwZWF0ZWREb3VibGVfOwogICAgICAgICAgICByZXBlYXRlZERvdWJsZV8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZERvdWJsZUlzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZERvdWJsZV8uYWRkQWxsKG90aGVyLnJlcGVhdGVkRG91YmxlXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEJvb2xfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkQm9vbF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkQm9vbF8gPSBvdGhlci5yZXBlYXRlZEJvb2xfOwogICAgICAgICAgICByZXBlYXRlZEJvb2xfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRCb29sSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkQm9vbF8uYWRkQWxsKG90aGVyLnJlcGVhdGVkQm9vbF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRTdHJpbmdfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkU3RyaW5nXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRTdHJpbmdfID0gb3RoZXIucmVwZWF0ZWRTdHJpbmdfOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFN0cmluZ0lzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZFN0cmluZ18uYWRkQWxsKG90aGVyLnJlcGVhdGVkU3RyaW5nXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEJ5dGVzXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEJ5dGVzXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRCeXRlc18gPSBvdGhlci5yZXBlYXRlZEJ5dGVzXzsKICAgICAgICAgICAgcmVwZWF0ZWRCeXRlc18ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEJ5dGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkQnl0ZXNfLmFkZEFsbChvdGhlci5yZXBlYXRlZEJ5dGVzXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkR3JvdXBfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBvdGhlci5yZXBlYXRlZEdyb3VwXzsKICAgICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDQwMCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBfLmFkZEFsbChvdGhlci5yZXBlYXRlZEdyb3VwXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRHcm91cF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBfID0gb3RoZXIucmVwZWF0ZWRHcm91cF87CiAgICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDA0MDApOwogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9IAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICBnZXRSZXBlYXRlZEdyb3VwRmllbGRCdWlsZGVyKCkgOiBudWxsOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyhvdGhlci5yZXBlYXRlZEdyb3VwXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyA9IG90aGVyLnJlcGVhdGVkTmVzdGVkTWVzc2FnZV87CiAgICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDA4MDApOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uYWRkQWxsKG90aGVyLnJlcGVhdGVkTmVzdGVkTWVzc2FnZV8pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8gPSBvdGhlci5yZXBlYXRlZE5lc3RlZE1lc3NhZ2VfOwogICAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAwODAwKTsKICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9IAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIucmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8gPSBvdGhlci5yZXBlYXRlZEZvcmVpZ25NZXNzYWdlXzsKICAgICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMTAwMCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmFkZEFsbChvdGhlci5yZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfID0gb3RoZXIucmVwZWF0ZWRGb3JlaWduTWVzc2FnZV87CiAgICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDEwMDApOwogICAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9IAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkgOiBudWxsOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyhvdGhlci5yZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyA9IG90aGVyLnJlcGVhdGVkSW1wb3J0TWVzc2FnZV87CiAgICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDIwMDApOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uYWRkQWxsKG90aGVyLnJlcGVhdGVkSW1wb3J0TWVzc2FnZV8pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8gPSBvdGhlci5yZXBlYXRlZEltcG9ydE1lc3NhZ2VfOwogICAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIucmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZE5lc3RlZEVudW1fLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkRW51bV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkTmVzdGVkRW51bV8gPSBvdGhlci5yZXBlYXRlZE5lc3RlZEVudW1fOwogICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwNDAwMCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZEVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRFbnVtXy5hZGRBbGwob3RoZXIucmVwZWF0ZWROZXN0ZWRFbnVtXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEZvcmVpZ25FbnVtXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25FbnVtXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8gPSBvdGhlci5yZXBlYXRlZEZvcmVpZ25FbnVtXzsKICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDgwMDApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGb3JlaWduRW51bUlzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZEZvcmVpZ25FbnVtXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRGb3JlaWduRW51bV8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRJbXBvcnRFbnVtXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEltcG9ydEVudW1fLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEltcG9ydEVudW1fID0gb3RoZXIucmVwZWF0ZWRJbXBvcnRFbnVtXzsKICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMTAwMDApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkSW1wb3J0RW51bV8uYWRkQWxsKG90aGVyLnJlcGVhdGVkSW1wb3J0RW51bV8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRTdHJpbmdQaWVjZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRTdHJpbmdQaWVjZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfID0gb3RoZXIucmVwZWF0ZWRTdHJpbmdQaWVjZV87CiAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAyMDAwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nUGllY2VJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRTdHJpbmdQaWVjZV8uYWRkQWxsKG90aGVyLnJlcGVhdGVkU3RyaW5nUGllY2VfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkQ29yZF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRDb3JkXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRDb3JkXyA9IG90aGVyLnJlcGVhdGVkQ29yZF87CiAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDA0MDAwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQ29yZElzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZENvcmRfLmFkZEFsbChvdGhlci5yZXBlYXRlZENvcmRfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRMYXp5TWVzc2FnZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXyA9IG90aGVyLnJlcGVhdGVkTGF6eU1lc3NhZ2VfOwogICAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDgwMDAwKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZExhenlNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8uYWRkQWxsKG90aGVyLnJlcGVhdGVkTGF6eU1lc3NhZ2VfKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZExhenlNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8gPSBvdGhlci5yZXBlYXRlZExhenlNZXNzYWdlXzsKICAgICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDA4MDAwMCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLnJlcGVhdGVkTGF6eU1lc3NhZ2VfKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdEludDMyKCkpIHsKICAgICAgICAgIHNldERlZmF1bHRJbnQzMihvdGhlci5nZXREZWZhdWx0SW50MzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0SW50NjQoKSkgewogICAgICAgICAgc2V0RGVmYXVsdEludDY0KG90aGVyLmdldERlZmF1bHRJbnQ2NCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRVaW50MzIoKSkgewogICAgICAgICAgc2V0RGVmYXVsdFVpbnQzMihvdGhlci5nZXREZWZhdWx0VWludDMyKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdFVpbnQ2NCgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0VWludDY0KG90aGVyLmdldERlZmF1bHRVaW50NjQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0U2ludDMyKCkpIHsKICAgICAgICAgIHNldERlZmF1bHRTaW50MzIob3RoZXIuZ2V0RGVmYXVsdFNpbnQzMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRTaW50NjQoKSkgewogICAgICAgICAgc2V0RGVmYXVsdFNpbnQ2NChvdGhlci5nZXREZWZhdWx0U2ludDY0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdEZpeGVkMzIoKSkgewogICAgICAgICAgc2V0RGVmYXVsdEZpeGVkMzIob3RoZXIuZ2V0RGVmYXVsdEZpeGVkMzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0Rml4ZWQ2NCgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0Rml4ZWQ2NChvdGhlci5nZXREZWZhdWx0Rml4ZWQ2NCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRTZml4ZWQzMigpKSB7CiAgICAgICAgICBzZXREZWZhdWx0U2ZpeGVkMzIob3RoZXIuZ2V0RGVmYXVsdFNmaXhlZDMyKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdFNmaXhlZDY0KCkpIHsKICAgICAgICAgIHNldERlZmF1bHRTZml4ZWQ2NChvdGhlci5nZXREZWZhdWx0U2ZpeGVkNjQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0RmxvYXQoKSkgewogICAgICAgICAgc2V0RGVmYXVsdEZsb2F0KG90aGVyLmdldERlZmF1bHRGbG9hdCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHREb3VibGUoKSkgewogICAgICAgICAgc2V0RGVmYXVsdERvdWJsZShvdGhlci5nZXREZWZhdWx0RG91YmxlKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdEJvb2woKSkgewogICAgICAgICAgc2V0RGVmYXVsdEJvb2wob3RoZXIuZ2V0RGVmYXVsdEJvb2woKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0U3RyaW5nKCkpIHsKICAgICAgICAgIGRlZmF1bHRTdHJpbmdfID0gb3RoZXIuZGVmYXVsdFN0cmluZ187CiAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRCeXRlcygpKSB7CiAgICAgICAgICBzZXREZWZhdWx0Qnl0ZXMob3RoZXIuZ2V0RGVmYXVsdEJ5dGVzKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdE5lc3RlZEVudW0oKSkgewogICAgICAgICAgc2V0RGVmYXVsdE5lc3RlZEVudW0ob3RoZXIuZ2V0RGVmYXVsdE5lc3RlZEVudW0oKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0Rm9yZWlnbkVudW0oKSkgewogICAgICAgICAgc2V0RGVmYXVsdEZvcmVpZ25FbnVtKG90aGVyLmdldERlZmF1bHRGb3JlaWduRW51bSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRJbXBvcnRFbnVtKCkpIHsKICAgICAgICAgIHNldERlZmF1bHRJbXBvcnRFbnVtKG90aGVyLmdldERlZmF1bHRJbXBvcnRFbnVtKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdFN0cmluZ1BpZWNlKCkpIHsKICAgICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSBvdGhlci5kZWZhdWx0U3RyaW5nUGllY2VfOwogICAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDQwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0Q29yZCgpKSB7CiAgICAgICAgICBkZWZhdWx0Q29yZF8gPSBvdGhlci5kZWZhdWx0Q29yZF87CiAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlY2VwdGl2ZWx5TmFtZWRMaXN0KCkpIHsKICAgICAgICAgIHNldERlY2VwdGl2ZWx5TmFtZWRMaXN0KG90aGVyLmdldERlY2VwdGl2ZWx5TmFtZWRMaXN0KCkpOwogICAgICAgIH0KICAgICAgICBzd2l0Y2ggKG90aGVyLmdldE9uZW9mRmllbGRDYXNlKCkpIHsKICAgICAgICAgIGNhc2UgT05FT0ZfVUlOVDMyOiB7CiAgICAgICAgICAgIHNldE9uZW9mVWludDMyKG90aGVyLmdldE9uZW9mVWludDMyKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfTkVTVEVEX01FU1NBR0U6IHsKICAgICAgICAgICAgbWVyZ2VPbmVvZk5lc3RlZE1lc3NhZ2Uob3RoZXIuZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfU1RSSU5HOiB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMzsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBvdGhlci5vbmVvZkZpZWxkXzsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9CWVRFUzogewogICAgICAgICAgICBzZXRPbmVvZkJ5dGVzKG90aGVyLmdldE9uZW9mQnl0ZXMoKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9MQVpZX05FU1RFRF9NRVNTQUdFOiB7CiAgICAgICAgICAgIG1lcmdlT25lb2ZMYXp5TmVzdGVkTWVzc2FnZShvdGhlci5nZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfTkVTVEVEX01FU1NBR0UyOiB7CiAgICAgICAgICAgIG1lcmdlT25lb2ZOZXN0ZWRNZXNzYWdlMihvdGhlci5nZXRPbmVvZk5lc3RlZE1lc3NhZ2UyKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZGSUVMRF9OT1RfU0VUOiB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsSW50MzJfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGNhc2UgMTY6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsSW50NjRfID0gaW5wdXQucmVhZEludDY0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYKICAgICAgICAgICAgICBjYXNlIDI0OiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbFVpbnQzMl8gPSBpbnB1dC5yZWFkVUludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjQKICAgICAgICAgICAgICBjYXNlIDMyOiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbFVpbnQ2NF8gPSBpbnB1dC5yZWFkVUludDY0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzIKICAgICAgICAgICAgICBjYXNlIDQwOiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbFNpbnQzMl8gPSBpbnB1dC5yZWFkU0ludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDAKICAgICAgICAgICAgICBjYXNlIDQ4OiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbFNpbnQ2NF8gPSBpbnB1dC5yZWFkU0ludDY0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDgKICAgICAgICAgICAgICBjYXNlIDYxOiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbEZpeGVkMzJfID0gaW5wdXQucmVhZEZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA2MQogICAgICAgICAgICAgIGNhc2UgNjU6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsRml4ZWQ2NF8gPSBpbnB1dC5yZWFkRml4ZWQ2NCgpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDY1CiAgICAgICAgICAgICAgY2FzZSA3NzogewogICAgICAgICAgICAgICAgb3B0aW9uYWxTZml4ZWQzMl8gPSBpbnB1dC5yZWFkU0ZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3NwogICAgICAgICAgICAgIGNhc2UgODE6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsU2ZpeGVkNjRfID0gaW5wdXQucmVhZFNGaXhlZDY0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODEKICAgICAgICAgICAgICBjYXNlIDkzOiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbEZsb2F0XyA9IGlucHV0LnJlYWRGbG9hdCgpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDkzCiAgICAgICAgICAgICAgY2FzZSA5NzogewogICAgICAgICAgICAgICAgb3B0aW9uYWxEb3VibGVfID0gaW5wdXQucmVhZERvdWJsZSgpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDk3CiAgICAgICAgICAgICAgY2FzZSAxMDQ6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsQm9vbF8gPSBpbnB1dC5yZWFkQm9vbCgpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEwNAogICAgICAgICAgICAgIGNhc2UgMTE0OiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbFN0cmluZ18gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMTQKICAgICAgICAgICAgICBjYXNlIDEyMjogewogICAgICAgICAgICAgICAgb3B0aW9uYWxCeXRlc18gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwNDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMjIKICAgICAgICAgICAgICBjYXNlIDEzMTogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZEdyb3VwKDE2LAogICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEzMQogICAgICAgICAgICAgIGNhc2UgMTQ2OiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE0NgogICAgICAgICAgICAgIGNhc2UgMTU0OiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAyMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNTQKICAgICAgICAgICAgICBjYXNlIDE2MjogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDA0MDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjIKICAgICAgICAgICAgICBjYXNlIDE2ODogewogICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDIxLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgb3B0aW9uYWxOZXN0ZWRFbnVtXyA9IHRtcFJhdzsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDgwMDAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2OAogICAgICAgICAgICAgIGNhc2UgMTc2OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoMjIsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBvcHRpb25hbEZvcmVpZ25FbnVtXyA9IHRtcFJhdzsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMTAwMDAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE3NgogICAgICAgICAgICAgIGNhc2UgMTg0OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDIzLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgb3B0aW9uYWxJbXBvcnRFbnVtXyA9IHRtcFJhdzsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMjAwMDAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE4NAogICAgICAgICAgICAgIGNhc2UgMTk0OiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwNDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE5NAogICAgICAgICAgICAgIGNhc2UgMjAyOiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbENvcmRfID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDA4MDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjAyCiAgICAgICAgICAgICAgY2FzZSAyMTA6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDEwMDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjEwCiAgICAgICAgICAgICAgY2FzZSAyMTg6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAyMDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDIxOAogICAgICAgICAgICAgIGNhc2UgMjI2OiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDQwMDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjI2CiAgICAgICAgICAgICAgY2FzZSAyNDg6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZEludDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjQ4CiAgICAgICAgICAgICAgY2FzZSAyNTA6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEludDMyXy5hZGRJbnQoaW5wdXQucmVhZEludDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI1MAogICAgICAgICAgICAgIGNhc2UgMjU2OiB7CiAgICAgICAgICAgICAgICBsb25nIHYgPSBpbnB1dC5yZWFkSW50NjQoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50NjRfLmFkZExvbmcodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjU2CiAgICAgICAgICAgICAgY2FzZSAyNTg6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEludDY0Xy5hZGRMb25nKGlucHV0LnJlYWRJbnQ2NCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyNTgKICAgICAgICAgICAgICBjYXNlIDI2NDogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkVUludDMyKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFVpbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRVaW50MzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyNjQKICAgICAgICAgICAgICBjYXNlIDI2NjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFVpbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZFVpbnQzMl8uYWRkSW50KGlucHV0LnJlYWRVSW50MzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjY2CiAgICAgICAgICAgICAgY2FzZSAyNzI6IHsKICAgICAgICAgICAgICAgIGxvbmcgdiA9IGlucHV0LnJlYWRVSW50NjQoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkVWludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZFVpbnQ2NF8uYWRkTG9uZyh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyNzIKICAgICAgICAgICAgICBjYXNlIDI3NDogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFVpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZFVpbnQ2NF8uYWRkTG9uZyhpbnB1dC5yZWFkVUludDY0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI3NAogICAgICAgICAgICAgIGNhc2UgMjgwOiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRTSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZFNpbnQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI4MAogICAgICAgICAgICAgIGNhc2UgMjgyOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkU2ludDMyXy5hZGRJbnQoaW5wdXQucmVhZFNJbnQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyODIKICAgICAgICAgICAgICBjYXNlIDI4ODogewogICAgICAgICAgICAgICAgbG9uZyB2ID0gaW5wdXQucmVhZFNJbnQ2NCgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkU2ludDY0Xy5hZGRMb25nKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI4OAogICAgICAgICAgICAgIGNhc2UgMjkwOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU2ludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkU2ludDY0Xy5hZGRMb25nKGlucHV0LnJlYWRTSW50NjQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjkwCiAgICAgICAgICAgICAgY2FzZSAzMDE6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZEZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzAxCiAgICAgICAgICAgICAgY2FzZSAyOTg6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoYWxsb2MgLyA0KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5hZGRJbnQoaW5wdXQucmVhZEZpeGVkMzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjk4CiAgICAgICAgICAgICAgY2FzZSAzMDU6IHsKICAgICAgICAgICAgICAgIGxvbmcgdiA9IGlucHV0LnJlYWRGaXhlZDY0KCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8uYWRkTG9uZyh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMDUKICAgICAgICAgICAgICBjYXNlIDMwNjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQ2NElzTXV0YWJsZShhbGxvYyAvIDgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEZpeGVkNjRfLmFkZExvbmcoaW5wdXQucmVhZEZpeGVkNjQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzA2CiAgICAgICAgICAgICAgY2FzZSAzMTc6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZFNGaXhlZDMyKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFNmaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZFNmaXhlZDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzE3CiAgICAgICAgICAgICAgY2FzZSAzMTQ6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFNmaXhlZDMySXNNdXRhYmxlKGFsbG9jIC8gNCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkMzJfLmFkZEludChpbnB1dC5yZWFkU0ZpeGVkMzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzE0CiAgICAgICAgICAgICAgY2FzZSAzMjE6IHsKICAgICAgICAgICAgICAgIGxvbmcgdiA9IGlucHV0LnJlYWRTRml4ZWQ2NCgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTZml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRTZml4ZWQ2NF8uYWRkTG9uZyh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMjEKICAgICAgICAgICAgICBjYXNlIDMyMjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU2ZpeGVkNjRJc011dGFibGUoYWxsb2MgLyA4KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRTZml4ZWQ2NF8uYWRkTG9uZyhpbnB1dC5yZWFkU0ZpeGVkNjQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzIyCiAgICAgICAgICAgICAgY2FzZSAzMzM6IHsKICAgICAgICAgICAgICAgIGZsb2F0IHYgPSBpbnB1dC5yZWFkRmxvYXQoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRmxvYXRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkRmxvYXRfLmFkZEZsb2F0KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDMzMwogICAgICAgICAgICAgIGNhc2UgMzMwOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGbG9hdElzTXV0YWJsZShhbGxvYyAvIDQpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEZsb2F0Xy5hZGRGbG9hdChpbnB1dC5yZWFkRmxvYXQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzMwCiAgICAgICAgICAgICAgY2FzZSAzMzc6IHsKICAgICAgICAgICAgICAgIGRvdWJsZSB2ID0gaW5wdXQucmVhZERvdWJsZSgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWREb3VibGVJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkRG91YmxlXy5hZGREb3VibGUodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzM3CiAgICAgICAgICAgICAgY2FzZSAzMzg6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZERvdWJsZUlzTXV0YWJsZShhbGxvYyAvIDgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZERvdWJsZV8uYWRkRG91YmxlKGlucHV0LnJlYWREb3VibGUoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzM4CiAgICAgICAgICAgICAgY2FzZSAzNDQ6IHsKICAgICAgICAgICAgICAgIGJvb2xlYW4gdiA9IGlucHV0LnJlYWRCb29sKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEJvb2xJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkQm9vbF8uYWRkQm9vbGVhbih2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzNDQKICAgICAgICAgICAgICBjYXNlIDM0NjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQm9vbElzTXV0YWJsZShhbGxvYyAvIDEpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEJvb2xfLmFkZEJvb2xlYW4oaW5wdXQucmVhZEJvb2woKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzQ2CiAgICAgICAgICAgICAgY2FzZSAzNTQ6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTdHJpbmdJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkU3RyaW5nXy5hZGQoYnMpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM1NAogICAgICAgICAgICAgIGNhc2UgMzYyOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdiA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRCeXRlc0lzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRCeXRlc18uYWRkKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM2MgogICAgICAgICAgICAgIGNhc2UgMzcxOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgbSA9CiAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZEdyb3VwKDQ2LAogICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwXy5hZGQobSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uYWRkTWVzc2FnZShtKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzNzEKICAgICAgICAgICAgICBjYXNlIDM4NjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG0gPQogICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5hZGQobSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM4NgogICAgICAgICAgICAgIGNhc2UgMzk0OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgbSA9CiAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmFkZChtKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM5NAogICAgICAgICAgICAgIGNhc2UgNDAyOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBtID0KICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5hZGQobSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQwMgogICAgICAgICAgICAgIGNhc2UgNDA4OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoNTEsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZEVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRFbnVtXy5hZGQodG1wUmF3KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0MDgKICAgICAgICAgICAgICBjYXNlIDQxMDogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IG9sZExpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICB3aGlsZShpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoNTEsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWROZXN0ZWRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRFbnVtXy5hZGQodG1wUmF3KTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQob2xkTGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQxMAogICAgICAgICAgICAgIGNhc2UgNDE2OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoNTIsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25FbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbkVudW1fLmFkZCh0bXBSYXcpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQxNgogICAgICAgICAgICAgIGNhc2UgNDE4OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgb2xkTGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIHdoaWxlKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg1MiwgdG1wUmF3KTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25FbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8uYWRkKHRtcFJhdyk7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KG9sZExpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0MTgKICAgICAgICAgICAgICBjYXNlIDQyNDogewogICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg1MywgdG1wUmF3KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0RW51bUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydEVudW1fLmFkZCh0bXBSYXcpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQyNAogICAgICAgICAgICAgIGNhc2UgNDI2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgb2xkTGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIHdoaWxlKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoNTMsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRFbnVtXy5hZGQodG1wUmF3KTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQob2xkTGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQyNgogICAgICAgICAgICAgIGNhc2UgNDM0OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nUGllY2VJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfLmFkZChicyk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDM0CiAgICAgICAgICAgICAgY2FzZSA0NDI6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRDb3JkSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZENvcmRfLmFkZChicyk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDQyCiAgICAgICAgICAgICAgY2FzZSA0NTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBtID0KICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLlBBUlNFUiwKICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTGF6eU1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8uYWRkKG0pOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UobSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDU4CiAgICAgICAgICAgICAgY2FzZSA0ODg6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRJbnQzMl8gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDEwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0ODgKICAgICAgICAgICAgICBjYXNlIDQ5NjogewogICAgICAgICAgICAgICAgZGVmYXVsdEludDY0XyA9IGlucHV0LnJlYWRJbnQ2NCgpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMjAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQ5NgogICAgICAgICAgICAgIGNhc2UgNTA0OiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0VWludDMyXyA9IGlucHV0LnJlYWRVSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDQwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1MDQKICAgICAgICAgICAgICBjYXNlIDUxMjogewogICAgICAgICAgICAgICAgZGVmYXVsdFVpbnQ2NF8gPSBpbnB1dC5yZWFkVUludDY0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDA4MDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTEyCiAgICAgICAgICAgICAgY2FzZSA1MjA6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRTaW50MzJfID0gaW5wdXQucmVhZFNJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAxMDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDUyMAogICAgICAgICAgICAgIGNhc2UgNTI4OiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0U2ludDY0XyA9IGlucHV0LnJlYWRTSW50NjQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMjAwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1MjgKICAgICAgICAgICAgICBjYXNlIDU0MTogewogICAgICAgICAgICAgICAgZGVmYXVsdEZpeGVkMzJfID0gaW5wdXQucmVhZEZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwNDAwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1NDEKICAgICAgICAgICAgICBjYXNlIDU0NTogewogICAgICAgICAgICAgICAgZGVmYXVsdEZpeGVkNjRfID0gaW5wdXQucmVhZEZpeGVkNjQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwODAwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1NDUKICAgICAgICAgICAgICBjYXNlIDU1NzogewogICAgICAgICAgICAgICAgZGVmYXVsdFNmaXhlZDMyXyA9IGlucHV0LnJlYWRTRml4ZWQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDEwMDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDU1NwogICAgICAgICAgICAgIGNhc2UgNTYxOiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0U2ZpeGVkNjRfID0gaW5wdXQucmVhZFNGaXhlZDY0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MjAwMDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTYxCiAgICAgICAgICAgICAgY2FzZSA1NzM6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRGbG9hdF8gPSBpbnB1dC5yZWFkRmxvYXQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHg0MDAwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1NzMKICAgICAgICAgICAgICBjYXNlIDU3NzogewogICAgICAgICAgICAgICAgZGVmYXVsdERvdWJsZV8gPSBpbnB1dC5yZWFkRG91YmxlKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4ODAwMDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTc3CiAgICAgICAgICAgICAgY2FzZSA1ODQ6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRCb29sXyA9IGlucHV0LnJlYWRCb29sKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTg0CiAgICAgICAgICAgICAgY2FzZSA1OTQ6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRTdHJpbmdfID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTk0CiAgICAgICAgICAgICAgY2FzZSA2MDI6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRCeXRlc18gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwNDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA2MDIKICAgICAgICAgICAgICBjYXNlIDY0ODogewogICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDgxLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZGVmYXVsdE5lc3RlZEVudW1fID0gdG1wUmF3OwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNjQ4CiAgICAgICAgICAgICAgY2FzZSA2NTY6IHsKICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg4MiwgdG1wUmF3KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGRlZmF1bHRGb3JlaWduRW51bV8gPSB0bXBSYXc7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAxMDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA2NTYKICAgICAgICAgICAgICBjYXNlIDY2NDogewogICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg4MywgdG1wUmF3KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGRlZmF1bHRJbXBvcnRFbnVtXyA9IHRtcFJhdzsKICAgICAgICAgICAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDIwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDY2NAogICAgICAgICAgICAgIGNhc2UgNjc0OiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNjc0CiAgICAgICAgICAgICAgY2FzZSA2ODI6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRDb3JkXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDY4MgogICAgICAgICAgICAgIGNhc2UgODg4OiB7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGlucHV0LnJlYWRVSW50MzIoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4ODgKICAgICAgICAgICAgICBjYXNlIDg5ODogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4OTgKICAgICAgICAgICAgICBjYXNlIDkwNjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTM7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGJzOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDkwNgogICAgICAgICAgICAgIGNhc2UgOTE0OiB7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTE0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDkxNAogICAgICAgICAgICAgIGNhc2UgOTIyOiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExNTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA5MjIKICAgICAgICAgICAgICBjYXNlIDkyODogewogICAgICAgICAgICAgICAgZGVjZXB0aXZlbHlOYW1lZExpc3RfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTI4CiAgICAgICAgICAgICAgY2FzZSA5Mzg6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9uZW9mTmVzdGVkTWVzc2FnZTJGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTE3OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDkzOAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBvbmVvZkZpZWxkXzsKICAgICAgcHVibGljIE9uZW9mRmllbGRDYXNlCiAgICAgICAgICBnZXRPbmVvZkZpZWxkQ2FzZSgpIHsKICAgICAgICByZXR1cm4gT25lb2ZGaWVsZENhc2UuZm9yTnVtYmVyKAogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8pOwogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mRmllbGQoKSB7CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMV87CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMl87CgogICAgICBwcml2YXRlIGludCBvcHRpb25hbEludDMyXyA7CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBTaW5ndWxhcgogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEludDMyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxJbnQzMigpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIFNpbmd1bGFyCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBvcHRpb25hbF9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEludDMyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE9wdGlvbmFsSW50MzIoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsSW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBTaW5ndWxhcgogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbEludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxJbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxJbnQzMl8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIFNpbmd1bGFyCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBvcHRpb25hbF9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsSW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIG9wdGlvbmFsSW50MzJfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBsb25nIG9wdGlvbmFsSW50NjRfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IG9wdGlvbmFsX2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxJbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW50NjQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBvcHRpb25hbF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEludDY0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRPcHRpb25hbEludDY0KCkgewogICAgICAgIHJldHVybiBvcHRpb25hbEludDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgb3B0aW9uYWxfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbEludDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxJbnQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsSW50NjRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBvcHRpb25hbF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsSW50NjQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgIG9wdGlvbmFsSW50NjRfID0gMEw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IG9wdGlvbmFsVWludDMyXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgb3B0aW9uYWxfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFVpbnQzMigpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBvcHRpb25hbF91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxVaW50MzIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0T3B0aW9uYWxVaW50MzIoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsVWludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIG9wdGlvbmFsX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsVWludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxVaW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsVWludDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIG9wdGlvbmFsX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsVWludDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICBvcHRpb25hbFVpbnQzMl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGxvbmcgb3B0aW9uYWxVaW50NjRfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQ2NCBvcHRpb25hbF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFVpbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsVWludDY0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IG9wdGlvbmFsX3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFVpbnQ2NC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0T3B0aW9uYWxVaW50NjQoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsVWludDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IG9wdGlvbmFsX3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsVWludDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxVaW50NjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBvcHRpb25hbFVpbnQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQ2NCBvcHRpb25hbF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbFVpbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwOCk7CiAgICAgICAgb3B0aW9uYWxVaW50NjRfID0gMEw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IG9wdGlvbmFsU2ludDMyXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgb3B0aW9uYWxfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTaW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFNpbnQzMigpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQzMiBvcHRpb25hbF9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTaW50MzIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0T3B0aW9uYWxTaW50MzIoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsU2ludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIG9wdGlvbmFsX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsU2ludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTaW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsU2ludDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIG9wdGlvbmFsX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsU2ludDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICBvcHRpb25hbFNpbnQzMl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGxvbmcgb3B0aW9uYWxTaW50NjRfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBvcHRpb25hbF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFNpbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU2ludDY0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDIwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IG9wdGlvbmFsX3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFNpbnQ2NC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0T3B0aW9uYWxTaW50NjQoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsU2ludDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IG9wdGlvbmFsX3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsU2ludDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTaW50NjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBvcHRpb25hbFNpbnQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBvcHRpb25hbF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbFNpbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAyMCk7CiAgICAgICAgb3B0aW9uYWxTaW50NjRfID0gMEw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IG9wdGlvbmFsRml4ZWQzMl8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBvcHRpb25hbF9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxGaXhlZDMyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxGaXhlZDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBvcHRpb25hbF9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRml4ZWQzMi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRPcHRpb25hbEZpeGVkMzIoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsRml4ZWQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkMzIgb3B0aW9uYWxfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsRml4ZWQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsRml4ZWQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxGaXhlZDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBvcHRpb25hbF9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxGaXhlZDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDQwKTsKICAgICAgICBvcHRpb25hbEZpeGVkMzJfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBsb25nIG9wdGlvbmFsRml4ZWQ2NF8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQ2NCBvcHRpb25hbF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxGaXhlZDY0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxGaXhlZDY0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDgwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQ2NCBvcHRpb25hbF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRml4ZWQ2NC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0T3B0aW9uYWxGaXhlZDY0KCkgewogICAgICAgIHJldHVybiBvcHRpb25hbEZpeGVkNjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IG9wdGlvbmFsX2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbEZpeGVkNjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEZpeGVkNjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBvcHRpb25hbEZpeGVkNjRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IG9wdGlvbmFsX2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEZpeGVkNjQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwODApOwogICAgICAgIG9wdGlvbmFsRml4ZWQ2NF8gPSAwTDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxTZml4ZWQzMl8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgb3B0aW9uYWxfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFNmaXhlZDMyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxTZml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIG9wdGlvbmFsX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ZpeGVkMzIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0T3B0aW9uYWxTZml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxTZml4ZWQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIG9wdGlvbmFsX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxTZml4ZWQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsU2ZpeGVkMzIoaW50IHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsU2ZpeGVkMzJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQzMiBvcHRpb25hbF9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsU2ZpeGVkMzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAxMDApOwogICAgICAgIG9wdGlvbmFsU2ZpeGVkMzJfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBsb25nIG9wdGlvbmFsU2ZpeGVkNjRfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IG9wdGlvbmFsX3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU2ZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFNmaXhlZDY0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMjAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgb3B0aW9uYWxfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ZpeGVkNjQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE9wdGlvbmFsU2ZpeGVkNjQoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsU2ZpeGVkNjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBvcHRpb25hbF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbFNmaXhlZDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTZml4ZWQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsU2ZpeGVkNjRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBvcHRpb25hbF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbFNmaXhlZDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMjAwKTsKICAgICAgICBvcHRpb25hbFNmaXhlZDY0XyA9IDBMOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGZsb2F0IG9wdGlvbmFsRmxvYXRfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IG9wdGlvbmFsX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRmxvYXQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZsb2F0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwNDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgb3B0aW9uYWxfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRmxvYXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmbG9hdCBnZXRPcHRpb25hbEZsb2F0KCkgewogICAgICAgIHJldHVybiBvcHRpb25hbEZsb2F0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgb3B0aW9uYWxfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxGbG9hdCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsRmxvYXQoZmxvYXQgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxGbG9hdF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IG9wdGlvbmFsX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsRmxvYXQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDA0MDApOwogICAgICAgIG9wdGlvbmFsRmxvYXRfID0gMEY7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgZG91YmxlIG9wdGlvbmFsRG91YmxlXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgb3B0aW9uYWxfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRG91YmxlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxEb3VibGUoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDA4MDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgb3B0aW9uYWxfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbERvdWJsZS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGRvdWJsZSBnZXRPcHRpb25hbERvdWJsZSgpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxEb3VibGVfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgb3B0aW9uYWxfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsRG91YmxlIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxEb3VibGUoZG91YmxlIHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsRG91YmxlXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIG9wdGlvbmFsX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbERvdWJsZSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDgwMCk7CiAgICAgICAgb3B0aW9uYWxEb3VibGVfID0gMEQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgYm9vbGVhbiBvcHRpb25hbEJvb2xfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgb3B0aW9uYWxfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEJvb2wgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEJvb2woKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDEwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBib29sIG9wdGlvbmFsX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQm9vbC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gZ2V0T3B0aW9uYWxCb29sKCkgewogICAgICAgIHJldHVybiBvcHRpb25hbEJvb2xfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBib29sIG9wdGlvbmFsX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxCb29sIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxCb29sKGJvb2xlYW4gdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxCb29sXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBvcHRpb25hbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsQm9vbCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMTAwMCk7CiAgICAgICAgb3B0aW9uYWxCb29sXyA9IGZhbHNlOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3Qgb3B0aW9uYWxTdHJpbmdfID0gIiI7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAyMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTdHJpbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPcHRpb25hbFN0cmluZygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IG9wdGlvbmFsU3RyaW5nXzsKICAgICAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0KICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IHM7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxTdHJpbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXRPcHRpb25hbFN0cmluZ0J5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxTdHJpbmdfOwogICAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBTdHJpbmcpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgICBvcHRpb25hbFN0cmluZ18gPSBiOwogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbFN0cmluZ18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDIwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxTdHJpbmcoKSB7CiAgICAgICAgb3B0aW9uYWxTdHJpbmdfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0T3B0aW9uYWxTdHJpbmcoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMjAwMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIG9wdGlvbmFsU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTdHJpbmdCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb3B0aW9uYWxTdHJpbmdfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBvcHRpb25hbEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIG9wdGlvbmFsX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEJ5dGVzKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDA0MDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQnl0ZXMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T3B0aW9uYWxCeXRlcygpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxCeXRlc187CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIG9wdGlvbmFsX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsQnl0ZXMgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEJ5dGVzKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb3B0aW9uYWxCeXRlc18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIG9wdGlvbmFsX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsQnl0ZXMoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDQwMDApOwogICAgICAgIG9wdGlvbmFsQnl0ZXNfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0T3B0aW9uYWxCeXRlcygpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBvcHRpb25hbEdyb3VwXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyPiBvcHRpb25hbEdyb3VwQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbGdyb3VwIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsR3JvdXAoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDgwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxncm91cC4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgZ2V0T3B0aW9uYWxHcm91cCgpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxHcm91cF87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEdyb3VwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvcHRpb25hbEdyb3VwXyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEdyb3VwKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZU9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwODAwMCkgIT0gMCkgJiYKICAgICAgICAgICAgb3B0aW9uYWxHcm91cF8gIT0gbnVsbCAmJgogICAgICAgICAgICBvcHRpb25hbEdyb3VwXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEJ1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbEdyb3VwXyAhPSBudWxsKSB7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxNiB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEdyb3VwKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDA4MDAwKTsKICAgICAgICBvcHRpb25hbEdyb3VwXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxNiB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBCdWlsZGVyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gZ2V0T3B0aW9uYWxHcm91cEZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXAoKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsTmVzdGVkTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMTAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2UgPSAxODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsTmVzdGVkTWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMTAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VPcHRpb25hbE5lc3RlZE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDEwMDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbE5lc3RlZE1lc3NhZ2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2UgPSAxODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsTmVzdGVkTWVzc2FnZSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAxMDAwMCk7CiAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsTmVzdGVkTWVzc2FnZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9mb3JlaWduX21lc3NhZ2UgPSAxOTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxGb3JlaWduTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDIwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZvcmVpZ25NZXNzYWdlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGlmIChvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9mb3JlaWduX21lc3NhZ2UgPSAxOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAyMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxGb3JlaWduTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDIwMDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyAhPSBudWxsICYmCiAgICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAyMDAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDIwMDAwKTsKICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxGb3JlaWduTWVzc2FnZV8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxGb3JlaWduTWVzc2FnZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9mb3JlaWduX21lc3NhZ2UgPSAxOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbEltcG9ydE1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXI+IG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEltcG9ydE1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDQwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbXBvcnRNZXNzYWdlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZSgpIHsKICAgICAgICBpZiAob3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxJbXBvcnRNZXNzYWdlXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEltcG9ydE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwNDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEltcG9ydE1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwNDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZU9wdGlvbmFsSW1wb3J0TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDA0MDAwMCkgIT0gMCkgJiYKICAgICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyAhPSBudWxsICYmCiAgICAgICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDA0MDAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDQwMDAwKTsKICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDQwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRPcHRpb25hbEltcG9ydE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsSW1wb3J0TWVzc2FnZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IG9wdGlvbmFsTmVzdGVkRW51bV8gPSAxOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gb3B0aW9uYWxfbmVzdGVkX2VudW0gPSAyMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxOZXN0ZWRFbnVtIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxOZXN0ZWRFbnVtKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDgwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gb3B0aW9uYWxfbmVzdGVkX2VudW0gPSAyMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTmVzdGVkRW51bS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBnZXRPcHRpb25hbE5lc3RlZEVudW0oKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5mb3JOdW1iZXIob3B0aW9uYWxOZXN0ZWRFbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLkZPTyA6IHJlc3VsdDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gb3B0aW9uYWxfbmVzdGVkX2VudW0gPSAyMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxOZXN0ZWRFbnVtIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxOZXN0ZWRFbnVtKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDgwMDAwOwogICAgICAgIG9wdGlvbmFsTmVzdGVkRW51bV8gPSB2YWx1ZS5nZXROdW1iZXIoKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gb3B0aW9uYWxfbmVzdGVkX2VudW0gPSAyMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxOZXN0ZWRFbnVtKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDgwMDAwKTsKICAgICAgICBvcHRpb25hbE5lc3RlZEVudW1fID0gMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxGb3JlaWduRW51bV8gPSA0OwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9lbnVtID0gMjI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRm9yZWlnbkVudW0gZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZvcmVpZ25FbnVtKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMTAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9lbnVtID0gMjI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZvcmVpZ25FbnVtLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldE9wdGlvbmFsRm9yZWlnbkVudW0oKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIob3B0aW9uYWxGb3JlaWduRW51bV8pOwogICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5GT1JFSUdOX0xJVEVfRk9PIDogcmVzdWx0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9mb3JlaWduX2VudW0gPSAyMjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxGb3JlaWduRW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsRm9yZWlnbkVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAxMDAwMDA7CiAgICAgICAgb3B0aW9uYWxGb3JlaWduRW51bV8gPSB2YWx1ZS5nZXROdW1iZXIoKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9lbnVtID0gMjI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsRm9yZWlnbkVudW0oKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAxMDAwMDApOwogICAgICAgIG9wdGlvbmFsRm9yZWlnbkVudW1fID0gNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxJbXBvcnRFbnVtXyA9IDc7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIG9wdGlvbmFsX2ltcG9ydF9lbnVtID0gMjM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW1wb3J0RW51bSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW1wb3J0RW51bSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDIwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgb3B0aW9uYWxfaW1wb3J0X2VudW0gPSAyMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW1wb3J0RW51bS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIGdldE9wdGlvbmFsSW1wb3J0RW51bSgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5mb3JOdW1iZXIob3B0aW9uYWxJbXBvcnRFbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuSU1QT1JUX0xJVEVfRk9PIDogcmVzdWx0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIG9wdGlvbmFsX2ltcG9ydF9lbnVtID0gMjM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsSW1wb3J0RW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsSW1wb3J0RW51bShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMjAwMDAwOwogICAgICAgIG9wdGlvbmFsSW1wb3J0RW51bV8gPSB2YWx1ZS5nZXROdW1iZXIoKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBvcHRpb25hbF9pbXBvcnRfZW51bSA9IDIzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEltcG9ydEVudW0oKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAyMDAwMDApOwogICAgICAgIG9wdGlvbmFsSW1wb3J0RW51bV8gPSA3OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3Qgb3B0aW9uYWxTdHJpbmdQaWVjZV8gPSAiIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFN0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nUGllY2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDA0MDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nX3BpZWNlID0gMjQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU3RyaW5nUGllY2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPcHRpb25hbFN0cmluZ1BpZWNlKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxTdHJpbmdQaWVjZV87CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9IHM7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nX3BpZWNlID0gMjQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZ1BpZWNlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0T3B0aW9uYWxTdHJpbmdQaWVjZUJ5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxTdHJpbmdQaWVjZV87CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIG9wdGlvbmFsU3RyaW5nUGllY2VfID0gYjsKICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZ19waWVjZSA9IDI0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsU3RyaW5nUGllY2UgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFN0cmluZ1BpZWNlKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb3B0aW9uYWxTdHJpbmdQaWVjZV8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDA0MDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbFN0cmluZ1BpZWNlKCkgewogICAgICAgIG9wdGlvbmFsU3RyaW5nUGllY2VfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0T3B0aW9uYWxTdHJpbmdQaWVjZSgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwNDAwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZ19waWVjZSA9IDI0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZ1BpZWNlIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTdHJpbmdQaWVjZUJ5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDQwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLmxhbmcuT2JqZWN0IG9wdGlvbmFsQ29yZF8gPSAiIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9jb3JkID0gMjUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbENvcmQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDA4MDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxDb3JkLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T3B0aW9uYWxDb3JkKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxDb3JkXzsKICAgICAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0KICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICAgIG9wdGlvbmFsQ29yZF8gPSBzOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX2NvcmQgPSAyNSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbENvcmQuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXRPcHRpb25hbENvcmRCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IG9wdGlvbmFsQ29yZF87CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIG9wdGlvbmFsQ29yZF8gPSBiOwogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbENvcmQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbENvcmQoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbENvcmRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwODAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbENvcmQoKSB7CiAgICAgICAgb3B0aW9uYWxDb3JkXyA9IGdldERlZmF1bHRJbnN0YW5jZSgpLmdldE9wdGlvbmFsQ29yZCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwODAwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX2NvcmQgPSAyNSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIG9wdGlvbmFsQ29yZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsQ29yZEJ5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbENvcmRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwODAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4gb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDEwMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkgewogICAgICAgIGlmIChvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMTAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMTAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAxMDAwMDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAxMDAwMDAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDEwMDAwMDApOwogICAgICAgIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDEwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIERlZmluZWQgaW4gdW5pdHRlc3RfaW1wb3J0X3B1YmxpYy5wcm90bwogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2UgPSAyNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxMYXp5TWVzc2FnZV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbGF6eV9tZXNzYWdlID0gMjcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxMYXp5TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbExhenlNZXNzYWdlKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAyMDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbGF6eV9tZXNzYWdlID0gMjcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTGF6eU1lc3NhZ2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxMYXp5TWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsTGF6eU1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxMYXp5TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDIwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxMYXp5TWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDIwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VPcHRpb25hbExhenlNZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDIwMDAwMDApICE9IDApICYmCiAgICAgICAgICAgIG9wdGlvbmFsTGF6eU1lc3NhZ2VfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZV8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsTGF6eU1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgIH0KICAgICAgICBpZiAob3B0aW9uYWxMYXp5TWVzc2FnZV8gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAyMDAwMDAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxMYXp5TWVzc2FnZSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMjAwMDAwMCk7CiAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBnZXRPcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDIwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbExhenlNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbExhenlNZXNzYWdlXyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbExhenlNZXNzYWdlXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbExhenlNZXNzYWdlKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDA0MDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZS4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF91bnZlcmlmaWVkX2xhenlfbWVzc2FnZSA9IDI4IFt1bnZlcmlmaWVkX2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDQwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwNDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwNDAwMDAwMCkgIT0gMCkgJiYKICAgICAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyAhPSBudWxsKSB7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDQwMDAwMDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDQwMDAwMDApOwogICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDA0MDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZV8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRJbnQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW50MzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkSW50MzJfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDA4MDAwMDAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBSZXBlYXRlZAogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAzMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRSZXBlYXRlZEludDMyTGlzdCgpIHsKICAgICAgICByZXBlYXRlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBSZXBlYXRlZAogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAzMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBSZXBlYXRlZAogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAzMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogUmVwZWF0ZWQKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMzE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRJbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW50MzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDA4MDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBSZXBlYXRlZAogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAzMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRJbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkSW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEludDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwODAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogUmVwZWF0ZWQKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMzE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRJbnQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRJbnQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwODAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogUmVwZWF0ZWQKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMzE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkSW50MzIoKSB7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwODAwMDAwMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCByZXBlYXRlZEludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkSW50NjRJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEludDY0Xy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRJbnQ2NF8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRJbnQ2NF8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MTAwMDAwMDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHJlcGVhdGVkX2ludDY0ID0gMzI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0UmVwZWF0ZWRJbnQ2NExpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRJbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZEludDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcmVwZWF0ZWRfaW50NjQgPSAzMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50NjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50NjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQ2NF8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCByZXBlYXRlZF9pbnQ2NCA9IDMyOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGxvbmcgZ2V0UmVwZWF0ZWRJbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHJlcGVhdGVkX2ludDY0ID0gMzI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRJbnQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW50NjQoCiAgICAgICAgICBpbnQgaW5kZXgsIGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkSW50NjRfLnNldExvbmcoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MTAwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHJlcGVhdGVkX2ludDY0ID0gMzI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkSW50NjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkSW50NjRfLmFkZExvbmcodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgxMDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcmVwZWF0ZWRfaW50NjQgPSAzMjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkSW50NjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEludDY0KAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZEludDY0Xyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDEwMDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCByZXBlYXRlZF9pbnQ2NCA9IDMyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEludDY0KCkgewogICAgICAgIHJlcGVhdGVkSW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDEwMDAwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRVaW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZFVpbnQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkVWludDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRVaW50MzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkVWludDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgyMDAwMDAwMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHJlcGVhdGVkX3VpbnQzMiA9IDMzOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRVaW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRSZXBlYXRlZFVpbnQzMkxpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRVaW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcmVwZWF0ZWRfdWludDMyID0gMzM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFVpbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRVaW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRVaW50MzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHJlcGVhdGVkX3VpbnQzMiA9IDMzOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkVWludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRVaW50MzIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkVWludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcmVwZWF0ZWRfdWludDMyID0gMzM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRVaW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZFVpbnQzMigKICAgICAgICAgIGludCBpbmRleCwgaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRVaW50MzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgyMDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHJlcGVhdGVkX3VpbnQzMiA9IDMzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZFVpbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkVWludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZFVpbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkVWludDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgyMDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHJlcGVhdGVkX3VpbnQzMiA9IDMzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWRVaW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZFVpbnQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkVWludDMyXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDIwMDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcmVwZWF0ZWRfdWludDMyID0gMzM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkVWludDMyKCkgewogICAgICAgIHJlcGVhdGVkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDIwMDAwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHJlcGVhdGVkVWludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkVWludDY0SXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRVaW50NjRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZFVpbnQ2NF8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRVaW50NjRfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDQwMDAwMDAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcmVwZWF0ZWRfdWludDY0ID0gMzQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFVpbnQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldFJlcGVhdGVkVWludDY0TGlzdCgpIHsKICAgICAgICByZXBlYXRlZFVpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZFVpbnQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCByZXBlYXRlZF91aW50NjQgPSAzNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkVWludDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZFVpbnQ2NENvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZFVpbnQ2NF8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcmVwZWF0ZWRfdWludDY0ID0gMzQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRVaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGxvbmcgZ2V0UmVwZWF0ZWRVaW50NjQoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkVWludDY0Xy5nZXRMb25nKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHJlcGVhdGVkX3VpbnQ2NCA9IDM0OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkVWludDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRVaW50NjQoCiAgICAgICAgICBpbnQgaW5kZXgsIGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRVaW50NjRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFVpbnQ2NF8uc2V0TG9uZyhpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHg0MDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHJlcGVhdGVkX3VpbnQ2NCA9IDM0OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZFVpbnQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkVWludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRVaW50NjRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFVpbnQ2NF8uYWRkTG9uZyh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDQwMDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcmVwZWF0ZWRfdWludDY0ID0gMzQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZFVpbnQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkVWludDY0KAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRVaW50NjRJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRVaW50NjRfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4NDAwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCByZXBlYXRlZF91aW50NjQgPSAzNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRVaW50NjQoKSB7CiAgICAgICAgcmVwZWF0ZWRVaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDQwMDAwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRTaW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZFNpbnQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkU2ludDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRTaW50MzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkU2ludDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHg4MDAwMDAwMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHJlcGVhdGVkX3NpbnQzMiA9IDM1OzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTaW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRSZXBlYXRlZFNpbnQzMkxpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRTaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRTaW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcmVwZWF0ZWRfc2ludDMyID0gMzU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFNpbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTaW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRTaW50MzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHJlcGVhdGVkX3NpbnQzMiA9IDM1OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU2ludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTaW50MzIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU2ludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcmVwZWF0ZWRfc2ludDMyID0gMzU7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRTaW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZFNpbnQzMigKICAgICAgICAgIGludCBpbmRleCwgaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRTaW50MzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHg4MDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHJlcGVhdGVkX3NpbnQzMiA9IDM1OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZFNpbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkU2ludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZFNpbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkU2ludDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHg4MDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHJlcGVhdGVkX3NpbnQzMiA9IDM1OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWRTaW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZFNpbnQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkU2ludDMyXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDgwMDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcmVwZWF0ZWRfc2ludDMyID0gMzU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkU2ludDMyKCkgewogICAgICAgIHJlcGVhdGVkU2ludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDgwMDAwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHJlcGVhdGVkU2ludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkU2ludDY0SXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRTaW50NjRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZFNpbnQ2NF8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRTaW50NjRfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDAxOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcmVwZWF0ZWRfc2ludDY0ID0gMzY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFNpbnQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldFJlcGVhdGVkU2ludDY0TGlzdCgpIHsKICAgICAgICByZXBlYXRlZFNpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZFNpbnQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCByZXBlYXRlZF9zaW50NjQgPSAzNjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU2ludDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZFNpbnQ2NENvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZFNpbnQ2NF8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcmVwZWF0ZWRfc2ludDY0ID0gMzY7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGxvbmcgZ2V0UmVwZWF0ZWRTaW50NjQoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU2ludDY0Xy5nZXRMb25nKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHJlcGVhdGVkX3NpbnQ2NCA9IDM2OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkU2ludDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRTaW50NjQoCiAgICAgICAgICBpbnQgaW5kZXgsIGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFNpbnQ2NF8uc2V0TG9uZyhpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHJlcGVhdGVkX3NpbnQ2NCA9IDM2OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZFNpbnQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkU2ludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFNpbnQ2NF8uYWRkTG9uZyh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcmVwZWF0ZWRfc2ludDY0ID0gMzY7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZFNpbnQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkU2ludDY0KAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRTaW50NjRfKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCByZXBlYXRlZF9zaW50NjQgPSAzNjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRTaW50NjQoKSB7CiAgICAgICAgcmVwZWF0ZWRTaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRGaXhlZDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZEZpeGVkMzJfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDAyOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoaW50IGNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEZpeGVkMzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkRml4ZWQzMl8sIGNhcGFjaXR5KTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDAyOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAzNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDM3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGaXhlZDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDM3OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAzNzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEZpeGVkMzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpeGVkMzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEZpeGVkMzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMzc7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkRml4ZWQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRml4ZWQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMzc7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEZpeGVkMzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEZpeGVkMzIoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRGaXhlZDMyXyk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAzNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRGaXhlZDMyKCkgewogICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCByZXBlYXRlZEZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRGaXhlZDY0SXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRGaXhlZDY0Xy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRGaXhlZDY0XyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZEZpeGVkNjRfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDA0OwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEZpeGVkNjRJc011dGFibGUoaW50IGNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEZpeGVkNjRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZEZpeGVkNjRfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkRml4ZWQ2NF8sIGNhcGFjaXR5KTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDA0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHJlcGVhdGVkX2ZpeGVkNjQgPSAzODs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldFJlcGVhdGVkRml4ZWQ2NExpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGaXhlZDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZpeGVkNjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDY0Xy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRml4ZWQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgbG9uZyBnZXRSZXBlYXRlZEZpeGVkNjQoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkRml4ZWQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRml4ZWQ2NCgKICAgICAgICAgIGludCBpbmRleCwgbG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEZpeGVkNjRfLnNldExvbmcoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEZpeGVkNjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpeGVkNjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEZpeGVkNjRfLmFkZExvbmcodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCByZXBlYXRlZF9maXhlZDY0ID0gMzg7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEZpeGVkNjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEZpeGVkNjQoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRGaXhlZDY0Xyk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHJlcGVhdGVkX2ZpeGVkNjQgPSAzODs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRGaXhlZDY0KCkgewogICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDAwMDQpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZFNmaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRTZml4ZWQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkU2ZpeGVkMzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZFNmaXhlZDMyXyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZFNmaXhlZDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwODsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRTZml4ZWQzMklzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkU2ZpeGVkMzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZFNmaXhlZDMyXyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZFNmaXhlZDMyXywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDg7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHJlcGVhdGVkX3NmaXhlZDMyID0gMzk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFNmaXhlZDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UmVwZWF0ZWRTZml4ZWQzMkxpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRTZml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZFNmaXhlZDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcmVwZWF0ZWRfc2ZpeGVkMzIgPSAzOTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU2ZpeGVkMzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkU2ZpeGVkMzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRTZml4ZWQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiByZXBlYXRlZF9zZml4ZWQzMiA9IDM5OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU2ZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZFNmaXhlZDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZFNmaXhlZDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiByZXBlYXRlZF9zZml4ZWQzMiA9IDM5OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkU2ZpeGVkMzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZFNmaXhlZDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTZml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkU2ZpeGVkMzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcmVwZWF0ZWRfc2ZpeGVkMzIgPSAzOTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRTZml4ZWQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkU2ZpeGVkMzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkU2ZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFNmaXhlZDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcmVwZWF0ZWRfc2ZpeGVkMzIgPSAzOTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkU2ZpeGVkMzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZFNmaXhlZDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTZml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZFNmaXhlZDMyXyk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiByZXBlYXRlZF9zZml4ZWQzMiA9IDM5OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZFNmaXhlZDMyKCkgewogICAgICAgIHJlcGVhdGVkU2ZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDAwMDgpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcmVwZWF0ZWRTZml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZFNmaXhlZDY0SXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRTZml4ZWQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkNjRfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkU2ZpeGVkNjRfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDEwOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZFNmaXhlZDY0SXNNdXRhYmxlKGludCBjYXBhY2l0eSkgewogICAgICAgIGlmICghcmVwZWF0ZWRTZml4ZWQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkNjRfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkU2ZpeGVkNjRfLCBjYXBhY2l0eSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAxMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcmVwZWF0ZWRfc2ZpeGVkNjQgPSA0MDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU2ZpeGVkNjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRSZXBlYXRlZFNmaXhlZDY0TGlzdCgpIHsKICAgICAgICByZXBlYXRlZFNmaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU2ZpeGVkNjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCByZXBlYXRlZF9zZml4ZWQ2NCA9IDQwOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTZml4ZWQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTZml4ZWQ2NENvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZFNmaXhlZDY0Xy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHJlcGVhdGVkX3NmaXhlZDY0ID0gNDA7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTZml4ZWQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgbG9uZyBnZXRSZXBlYXRlZFNmaXhlZDY0KGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZFNmaXhlZDY0Xy5nZXRMb25nKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcmVwZWF0ZWRfc2ZpeGVkNjQgPSA0MDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZFNmaXhlZDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRTZml4ZWQ2NCgKICAgICAgICAgIGludCBpbmRleCwgbG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRTZml4ZWQ2NF8uc2V0TG9uZyhpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAxMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcmVwZWF0ZWRfc2ZpeGVkNjQgPSA0MDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRTZml4ZWQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkU2ZpeGVkNjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRTZml4ZWQ2NF8uYWRkTG9uZyh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDEwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCByZXBlYXRlZF9zZml4ZWQ2NCA9IDQwOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWRTZml4ZWQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkU2ZpeGVkNjQoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkU2ZpeGVkNjRfKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHJlcGVhdGVkX3NmaXhlZDY0ID0gNDA7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkU2ZpeGVkNjQoKSB7CiAgICAgICAgcmVwZWF0ZWRTZml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDAwMTApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRmxvYXRMaXN0IHJlcGVhdGVkRmxvYXRfID0gZW1wdHlGbG9hdExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkRmxvYXRJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEZsb2F0Xy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRGbG9hdF8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRGbG9hdF8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMjA7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkRmxvYXRJc011dGFibGUoaW50IGNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEZsb2F0Xy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRGbG9hdF8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRGbG9hdF8sIGNhcGFjaXR5KTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDIwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCByZXBlYXRlZF9mbG9hdCA9IDQxOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRGbG9hdC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgICBnZXRSZXBlYXRlZEZsb2F0TGlzdCgpIHsKICAgICAgICByZXBlYXRlZEZsb2F0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRmxvYXRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCByZXBlYXRlZF9mbG9hdCA9IDQxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGbG9hdC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGbG9hdENvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEZsb2F0Xy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHJlcGVhdGVkX2Zsb2F0ID0gNDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGbG9hdCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgZmxvYXQgZ2V0UmVwZWF0ZWRGbG9hdChpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRGbG9hdF8uZ2V0RmxvYXQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCByZXBlYXRlZF9mbG9hdCA9IDQxOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkRmxvYXQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZsb2F0KAogICAgICAgICAgaW50IGluZGV4LCBmbG9hdCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEZsb2F0SXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRGbG9hdF8uc2V0RmxvYXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHJlcGVhdGVkX2Zsb2F0ID0gNDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkRmxvYXQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZsb2F0KGZsb2F0IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkRmxvYXRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEZsb2F0Xy5hZGRGbG9hdCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDIwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCByZXBlYXRlZF9mbG9hdCA9IDQxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWRGbG9hdCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkRmxvYXQoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5GbG9hdD4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRGbG9hdElzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZEZsb2F0Xyk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDIwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCByZXBlYXRlZF9mbG9hdCA9IDQxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEZsb2F0KCkgewogICAgICAgIHJlcGVhdGVkRmxvYXRfID0gZW1wdHlGbG9hdExpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDAyMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Eb3VibGVMaXN0IHJlcGVhdGVkRG91YmxlXyA9IGVtcHR5RG91YmxlTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWREb3VibGVJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZERvdWJsZV8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkRG91YmxlXyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZERvdWJsZV8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwNDA7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkRG91YmxlSXNNdXRhYmxlKGludCBjYXBhY2l0eSkgewogICAgICAgIGlmICghcmVwZWF0ZWREb3VibGVfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZERvdWJsZV8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWREb3VibGVfLCBjYXBhY2l0eSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDA0MDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHJlcGVhdGVkX2RvdWJsZSA9IDQyOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWREb3VibGUuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkRvdWJsZT4KICAgICAgICAgIGdldFJlcGVhdGVkRG91YmxlTGlzdCgpIHsKICAgICAgICByZXBlYXRlZERvdWJsZV8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZERvdWJsZV87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSByZXBlYXRlZF9kb3VibGUgPSA0Mjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRG91YmxlLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZERvdWJsZUNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZERvdWJsZV8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcmVwZWF0ZWRfZG91YmxlID0gNDI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWREb3VibGUgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGRvdWJsZSBnZXRSZXBlYXRlZERvdWJsZShpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWREb3VibGVfLmdldERvdWJsZShpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSByZXBlYXRlZF9kb3VibGUgPSA0Mjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZERvdWJsZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRG91YmxlKAogICAgICAgICAgaW50IGluZGV4LCBkb3VibGUgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWREb3VibGVJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZERvdWJsZV8uc2V0RG91YmxlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDQwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcmVwZWF0ZWRfZG91YmxlID0gNDI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkRG91YmxlIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWREb3VibGUoZG91YmxlIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkRG91YmxlSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWREb3VibGVfLmFkZERvdWJsZSh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDQwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcmVwZWF0ZWRfZG91YmxlID0gNDI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZERvdWJsZSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkRG91YmxlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuRG91YmxlPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZERvdWJsZUlzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZERvdWJsZV8pOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHJlcGVhdGVkX2RvdWJsZSA9IDQyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZERvdWJsZSgpIHsKICAgICAgICByZXBlYXRlZERvdWJsZV8gPSBlbXB0eURvdWJsZUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Cb29sZWFuTGlzdCByZXBlYXRlZEJvb2xfID0gZW1wdHlCb29sZWFuTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRCb29sSXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRCb29sXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRCb29sXyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZEJvb2xfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDgwOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEJvb2xJc011dGFibGUoaW50IGNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEJvb2xfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZEJvb2xfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkQm9vbF8sIGNhcGFjaXR5KTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDgwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHJlcGVhdGVkX2Jvb2wgPSA0Mzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkQm9vbC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuQm9vbGVhbj4KICAgICAgICAgIGdldFJlcGVhdGVkQm9vbExpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRCb29sXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkQm9vbF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRCb29sLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEJvb2xDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRCb29sXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkQm9vbCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBnZXRSZXBlYXRlZEJvb2woaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkQm9vbF8uZ2V0Qm9vbGVhbihpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkQm9vbCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkQm9vbCgKICAgICAgICAgIGludCBpbmRleCwgYm9vbGVhbiB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEJvb2xJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEJvb2xfLnNldEJvb2xlYW4oaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEJvb2wgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEJvb2woYm9vbGVhbiB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEJvb2xJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEJvb2xfLmFkZEJvb2xlYW4odmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCByZXBlYXRlZF9ib29sID0gNDM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEJvb2wgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEJvb2woCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5Cb29sZWFuPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZEJvb2xJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRCb29sXyk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDgwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHJlcGVhdGVkX2Jvb2wgPSA0Mzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRCb29sKCkgewogICAgICAgIHJlcGVhdGVkQm9vbF8gPSBlbXB0eUJvb2xlYW5MaXN0KCk7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDAwODApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdCByZXBlYXRlZFN0cmluZ18gPQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRTdHJpbmdJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZFN0cmluZ18uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkU3RyaW5nXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QocmVwZWF0ZWRTdHJpbmdfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMTAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nID0gNDQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFN0cmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sU3RyaW5nTGlzdAogICAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdMaXN0KCkgewogICAgICAgIHJlcGVhdGVkU3RyaW5nXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZyA9IDQ0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTdHJpbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkU3RyaW5nQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFN0cmluZyBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRSZXBlYXRlZFN0cmluZyhpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdfLmdldChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHZhbHVlIHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkU3RyaW5nIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldFJlcGVhdGVkU3RyaW5nQnl0ZXMoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nXy5nZXRCeXRlU3RyaW5nKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZyA9IDQ0OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRTdHJpbmcoCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRTdHJpbmdfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDEwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZyA9IDQ0OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZFN0cmluZyB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkU3RyaW5nKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTdHJpbmdJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFN0cmluZ18uYWRkKHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkU3RyaW5nIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8amF2YS5sYW5nLlN0cmluZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTdHJpbmdJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRTdHJpbmdfKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRTdHJpbmcoKSB7CiAgICAgICAgcmVwZWF0ZWRTdHJpbmdfID0KICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdC5lbXB0eUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDEwMCk7OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nID0gNDQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZFN0cmluZyB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkU3RyaW5nQnl0ZXMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRTdHJpbmdfLmFkZCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMTAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuUHJvdG9idWZMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gcmVwZWF0ZWRCeXRlc18gPSBlbXB0eUxpc3QoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNsYXNzKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkQnl0ZXNJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEJ5dGVzXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRCeXRlc18gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRCeXRlc18pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAyMDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJ5dGVzIHJlcGVhdGVkX2J5dGVzID0gNDU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEJ5dGVzLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgICAgICAgIGdldFJlcGVhdGVkQnl0ZXNMaXN0KCkgewogICAgICAgIHJlcGVhdGVkQnl0ZXNfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRCeXRlc187CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJ5dGVzIHJlcGVhdGVkX2J5dGVzID0gNDU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEJ5dGVzLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEJ5dGVzQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkQnl0ZXNfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEJ5dGVzIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0UmVwZWF0ZWRCeXRlcyhpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRCeXRlc18uZ2V0KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEJ5dGVzIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRCeXRlcygKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBlbnN1cmVSZXBlYXRlZEJ5dGVzSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRCeXRlc18uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMjAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBieXRlcyByZXBlYXRlZF9ieXRlcyA9IDQ1OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEJ5dGVzIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRCeXRlcyhjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkQnl0ZXNJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEJ5dGVzXy5hZGQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDIwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkQnl0ZXMgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEJ5dGVzKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkQnl0ZXNJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRCeXRlc18pOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDIwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRCeXRlcygpIHsKICAgICAgICByZXBlYXRlZEJ5dGVzXyA9IGVtcHR5TGlzdChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY2xhc3MpOwogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAwMjAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXA+IHJlcGVhdGVkR3JvdXBfID0KICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCkgewogICAgICAgIGlmICghKChiaXRGaWVsZDFfICYgMHgwMDAwMDQwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwPihyZXBlYXRlZEdyb3VwXyk7CiAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgIH0KICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXI+IHJlcGVhdGVkR3JvdXBCdWlsZGVyXzsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXA+IGdldFJlcGVhdGVkR3JvdXBMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkR3JvdXBfKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5nZXRNZXNzYWdlTGlzdCgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkR3JvdXBDb3VudCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwXy5zaXplKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQnVpbGRlcl8uZ2V0Q291bnQoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBnZXRSZXBlYXRlZEdyb3VwKGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfLmdldChpbmRleCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQnVpbGRlcl8uZ2V0TWVzc2FnZShpbmRleCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkR3JvdXAoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEdyb3VwKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkR3JvdXBJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkR3JvdXBJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfLmFkZCh2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmFkZE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEdyb3VwKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cF8uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRHcm91cCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cF8uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uYWRkTWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkR3JvdXAoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cF8uYWRkKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRHcm91cCgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwPiB2YWx1ZXMpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkR3JvdXBJc011dGFibGUoKTsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEdyb3VwKCkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDQwMCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVJlcGVhdGVkR3JvdXAoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5yZW1vdmUoaW5kZXgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIgZ2V0UmVwZWF0ZWRHcm91cEJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRHcm91cEZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRHcm91cE9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfLmdldChpbmRleCk7ICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXI+IAogICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRHcm91cF8pOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIgYWRkUmVwZWF0ZWRHcm91cEJ1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkR3JvdXBGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlciBhZGRSZXBlYXRlZEdyb3VwQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEdyb3VwRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5CdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZEdyb3VwQnVpbGRlckxpc3QoKSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkR3JvdXBGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyTGlzdCgpOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyPiAKICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cE9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBfLAogICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMV8gJiAweDAwMDAwNDAwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoISgoYml0RmllbGQxXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPihyZXBlYXRlZE5lc3RlZE1lc3NhZ2VfKTsKICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDgwMDsKICAgICAgICAgfQogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl87CgogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlTGlzdCgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUNvdW50KCkgewogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5zaXplKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5nZXRDb3VudCgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkTmVzdGVkTWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uYWRkKHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWROZXN0ZWRNZXNzYWdlKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZE5lc3RlZE1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWROZXN0ZWRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTmVzdGVkTWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkTmVzdGVkTWVzc2FnZSgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiB2YWx1ZXMpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWROZXN0ZWRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyh2YWx1ZXMpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkTmVzdGVkTWVzc2FnZSgpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAwODAwKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVSZXBlYXRlZE5lc3RlZE1lc3NhZ2UoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLmdldChpbmRleCk7ICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gCiAgICAgICAgICAgZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VfKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGFkZFJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGFkZFJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLAogICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMV8gJiAweDAwMDAwODAwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9CiAgICAgICAgamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoISgoYml0RmllbGQxXyAmIDB4MDAwMDEwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IG5ldyBqYXZhLnV0aWwuQXJyYXlMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4ocmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8pOwogICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAxMDAwOwogICAgICAgICB9CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl87CgogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4gZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUxpc3QoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VDb3VudCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5zaXplKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZ2V0Q291bnQoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5nZXQoaW5kZXgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5hZGQodmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5hZGQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmFkZChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IHZhbHVlcykgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8pOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyh2YWx1ZXMpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMTAwMCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZU9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmdldChpbmRleCk7ICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBhZGRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBhZGRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlcj4gCiAgICAgICAgICAgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJMaXN0KCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXywKICAgICAgICAgICAgICAgICAgKChiaXRGaWVsZDFfICYgMHgwMDAwMTAwMCkgIT0gMCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGU+IHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkSW1wb3J0TWVzc2FnZUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoISgoYml0RmllbGQxXyAmIDB4MDAwMDIwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGU+KHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8pOwogICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAyMDAwOwogICAgICAgICB9CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyPiByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXzsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlPiBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlTGlzdCgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlQ291bnQoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLnNpemUoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW1wb3J0TWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW1wb3J0TWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uYWRkKHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLmFkZChpbmRleCwgdmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRJbXBvcnRNZXNzYWdlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkSW1wb3J0TWVzc2FnZSgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVJlcGVhdGVkSW1wb3J0TWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZU9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8pOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyIGFkZFJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyIGFkZFJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLAogICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMV8gJiAweDAwMDAyMDAwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IHJlcGVhdGVkTmVzdGVkRW51bV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkTmVzdGVkRW51bUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoISgoYml0RmllbGQxXyAmIDB4MDAwMDQwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8amF2YS5sYW5nLkludGVnZXI+KHJlcGVhdGVkTmVzdGVkRW51bV8pOwogICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDA0MDAwOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVwZWF0ZWRfbmVzdGVkX2VudW0gPSA1MTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkTmVzdGVkRW51bS4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+IGdldFJlcGVhdGVkTmVzdGVkRW51bUxpc3QoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyPAogICAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtPihyZXBlYXRlZE5lc3RlZEVudW1fLCByZXBlYXRlZE5lc3RlZEVudW1fY29udmVydGVyXyk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZE5lc3RlZEVudW0uCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkTmVzdGVkRW51bUNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZEVudW1fLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVwZWF0ZWRfbmVzdGVkX2VudW0gPSA1MTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZE5lc3RlZEVudW0gYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBnZXRSZXBlYXRlZE5lc3RlZEVudW0oaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkRW51bV9jb252ZXJ0ZXJfLmNvbnZlcnQocmVwZWF0ZWROZXN0ZWRFbnVtXy5nZXQoaW5kZXgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVwZWF0ZWRfbmVzdGVkX2VudW0gPSA1MTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZE5lc3RlZEVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZE5lc3RlZEVudW0oCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWROZXN0ZWRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWROZXN0ZWRFbnVtXy5zZXQoaW5kZXgsIHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVwZWF0ZWRfbmVzdGVkX2VudW0gPSA1MTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWROZXN0ZWRFbnVtIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWROZXN0ZWRFbnVtKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWROZXN0ZWRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWROZXN0ZWRFbnVtXy5hZGQodmFsdWUuZ2V0TnVtYmVyKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWROZXN0ZWRFbnVtIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWROZXN0ZWRFbnVtKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkRW51bUlzTXV0YWJsZSgpOwogICAgICAgIGZvciAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHZhbHVlIDogdmFsdWVzKSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fLmFkZCh2YWx1ZS5nZXROdW1iZXIoKSk7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZE5lc3RlZEVudW0oKSB7CiAgICAgICAgcmVwZWF0ZWROZXN0ZWRFbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwNDAwMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IHJlcGVhdGVkRm9yZWlnbkVudW1fID0KICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEZvcmVpZ25FbnVtSXNNdXRhYmxlKCkgewogICAgICAgIGlmICghKChiaXRGaWVsZDFfICYgMHgwMDAwODAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbkVudW1fID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8amF2YS5sYW5nLkludGVnZXI+KHJlcGVhdGVkRm9yZWlnbkVudW1fKTsKICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwODAwMDsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHJlcGVhdGVkX2ZvcmVpZ25fZW51bSA9IDUyOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRGb3JlaWduRW51bS4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IGdldFJlcGVhdGVkRm9yZWlnbkVudW1MaXN0KCkgewogICAgICAgIHJldHVybiBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5MaXN0QWRhcHRlcjwKICAgICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZT4ocmVwZWF0ZWRGb3JlaWduRW51bV8sIHJlcGVhdGVkRm9yZWlnbkVudW1fY29udmVydGVyXyk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHJlcGVhdGVkX2ZvcmVpZ25fZW51bSA9IDUyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGb3JlaWduRW51bS4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGb3JlaWduRW51bUNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25FbnVtXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHJlcGVhdGVkX2ZvcmVpZ25fZW51bSA9IDUyOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRm9yZWlnbkVudW0gYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25FbnVtX2NvbnZlcnRlcl8uY29udmVydChyZXBlYXRlZEZvcmVpZ25FbnVtXy5nZXQoaW5kZXgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9lbnVtID0gNTI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRGb3JlaWduRW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRm9yZWlnbkVudW0oCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRGb3JlaWduRW51bUlzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkRm9yZWlnbkVudW1fLnNldChpbmRleCwgdmFsdWUuZ2V0TnVtYmVyKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRGb3JlaWduRW51bSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRm9yZWlnbkVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25FbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8uYWRkKHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9lbnVtID0gNTI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEZvcmVpZ25FbnVtIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRGb3JlaWduRW51bSgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25FbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgZm9yIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdmFsdWUgOiB2YWx1ZXMpIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbkVudW1fLmFkZCh2YWx1ZS5nZXROdW1iZXIoKSk7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRGb3JlaWduRW51bSgpIHsKICAgICAgICByZXBlYXRlZEZvcmVpZ25FbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwODAwMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IHJlcGVhdGVkSW1wb3J0RW51bV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkSW1wb3J0RW51bUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoISgoYml0RmllbGQxXyAmIDB4MDAwMTAwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydEVudW1fID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8amF2YS5sYW5nLkludGVnZXI+KHJlcGVhdGVkSW1wb3J0RW51bV8pOwogICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDEwMDAwOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSByZXBlYXRlZF9pbXBvcnRfZW51bSA9IDUzOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbXBvcnRFbnVtLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlPiBnZXRSZXBlYXRlZEltcG9ydEVudW1MaXN0KCkgewogICAgICAgIHJldHVybiBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5MaXN0QWRhcHRlcjwKICAgICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlPihyZXBlYXRlZEltcG9ydEVudW1fLCByZXBlYXRlZEltcG9ydEVudW1fY29udmVydGVyXyk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW1wb3J0RW51bS4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0RW51bV8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbXBvcnRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSBnZXRSZXBlYXRlZEltcG9ydEVudW0oaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0RW51bV9jb252ZXJ0ZXJfLmNvbnZlcnQocmVwZWF0ZWRJbXBvcnRFbnVtXy5nZXQoaW5kZXgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSByZXBlYXRlZF9pbXBvcnRfZW51bSA9IDUzOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkSW1wb3J0RW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW1wb3J0RW51bSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0RW51bUlzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkSW1wb3J0RW51bV8uc2V0KGluZGV4LCB2YWx1ZS5nZXROdW1iZXIoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRJbXBvcnRFbnVtIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRJbXBvcnRFbnVtKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydEVudW1Jc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEltcG9ydEVudW1fLmFkZCh2YWx1ZS5nZXROdW1iZXIoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkSW1wb3J0RW51bSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkSW1wb3J0RW51bSgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGU+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0RW51bUlzTXV0YWJsZSgpOwogICAgICAgIGZvciAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgdmFsdWUgOiB2YWx1ZXMpIHsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0RW51bV8uYWRkKHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRJbXBvcnRFbnVtKCkgewogICAgICAgIHJlcGVhdGVkSW1wb3J0RW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMTAwMDApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdCByZXBlYXRlZFN0cmluZ1BpZWNlXyA9CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZFN0cmluZ1BpZWNlSXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRTdHJpbmdQaWVjZV8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdChyZXBlYXRlZFN0cmluZ1BpZWNlXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAyMDAwMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFN0cmluZ1BpZWNlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xTdHJpbmdMaXN0CiAgICAgICAgICBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlTGlzdCgpIHsKICAgICAgICByZXBlYXRlZFN0cmluZ1BpZWNlXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nUGllY2VfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU3RyaW5nUGllY2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkU3RyaW5nUGllY2VDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdQaWVjZV8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldFJlcGVhdGVkU3RyaW5nUGllY2UoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nUGllY2VfLmdldChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdmFsdWUgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBvZiB0aGUgcmVwZWF0ZWRTdHJpbmdQaWVjZSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlQnl0ZXMoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nUGllY2VfLmdldEJ5dGVTdHJpbmcoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRTdHJpbmdQaWVjZSgKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTdHJpbmdQaWVjZUlzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAyMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkU3RyaW5nUGllY2UgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZFN0cmluZ1BpZWNlKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTdHJpbmdQaWVjZUlzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfLmFkZCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDIwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkU3RyaW5nUGllY2UgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZFN0cmluZ1BpZWNlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPGphdmEubGFuZy5TdHJpbmc+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nUGllY2VJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRTdHJpbmdQaWVjZV8pOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAyMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkU3RyaW5nUGllY2UoKSB7CiAgICAgICAgcmVwZWF0ZWRTdHJpbmdQaWVjZV8gPQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDIwMDAwKTs7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBieXRlcyBvZiB0aGUgcmVwZWF0ZWRTdHJpbmdQaWVjZSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkU3RyaW5nUGllY2VCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRTdHJpbmdQaWVjZUlzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfLmFkZCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDIwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdCByZXBlYXRlZENvcmRfID0KICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdC5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkQ29yZElzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkQ29yZF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkQ29yZF8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0KHJlcGVhdGVkQ29yZF8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwNDAwMDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZENvcmQuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Qcm90b2NvbFN0cmluZ0xpc3QKICAgICAgICAgIGdldFJlcGVhdGVkQ29yZExpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRDb3JkXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkQ29yZF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZENvcmQuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkQ29yZENvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZENvcmRfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX2NvcmQgPSA1NSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZENvcmQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0UmVwZWF0ZWRDb3JkKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZENvcmRfLmdldChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB2YWx1ZSB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZENvcmQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0UmVwZWF0ZWRDb3JkQnl0ZXMoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkQ29yZF8uZ2V0Qnl0ZVN0cmluZyhpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRDb3JkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRDb3JkKAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBlbnN1cmVSZXBlYXRlZENvcmRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZENvcmRfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDA0MDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX2NvcmQgPSA1NSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRDb3JkIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRDb3JkKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRDb3JkSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRDb3JkXy5hZGQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDA0MDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX2NvcmQgPSA1NSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkQ29yZCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkQ29yZCgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTxqYXZhLmxhbmcuU3RyaW5nPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZENvcmRJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRDb3JkXyk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDQwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZENvcmQoKSB7CiAgICAgICAgcmVwZWF0ZWRDb3JkXyA9CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwNDAwMDApOzsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX2NvcmQgPSA1NSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkQ29yZCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkQ29yZEJ5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBlbnN1cmVSZXBlYXRlZENvcmRJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZENvcmRfLmFkZCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDQwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gcmVwZWF0ZWRMYXp5TWVzc2FnZV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkTGF6eU1lc3NhZ2VJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCEoKGJpdEZpZWxkMV8gJiAweDAwMDgwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8gPSBuZXcgamF2YS51dGlsLkFycmF5TGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+KHJlcGVhdGVkTGF6eU1lc3NhZ2VfKTsKICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDA4MDAwMDsKICAgICAgICAgfQogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUxpc3QoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRMYXp5TWVzc2FnZV8pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUNvdW50KCkgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLnNpemUoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5nZXRDb3VudCgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2UoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRMYXp5TWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTGF6eU1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkTGF6eU1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRMYXp5TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8uc2V0KGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRMYXp5TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRMYXp5TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8uYWRkKHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTGF6eU1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZExhenlNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXy5hZGQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZExhenlNZXNzYWdlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZExhenlNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXy5hZGQoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRMYXp5TWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZExhenlNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZExhenlNZXNzYWdlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IHZhbHVlcykgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRMYXp5TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRMYXp5TWVzc2FnZV8pOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyh2YWx1ZXMpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkTGF6eU1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDgwMDAwKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlUmVwZWF0ZWRMYXp5TWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTGF6eU1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBnZXRSZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZExhenlNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRSZXBlYXRlZExhenlNZXNzYWdlT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZV8uZ2V0KGluZGV4KTsgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gCiAgICAgICAgICAgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZU9yQnVpbGRlckxpc3QoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZExhenlNZXNzYWdlXyk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBhZGRSZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGFkZFJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXI+IAogICAgICAgICAgIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXJMaXN0KCk7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8sCiAgICAgICAgICAgICAgICAgICgoYml0RmllbGQxXyAmIDB4MDAwODAwMDApICE9IDApLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBkZWZhdWx0SW50MzJfID0gNDE7CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBTaW5ndWxhciB3aXRoIGRlZmF1bHRzCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWZhdWx0X2ludDMyID0gNjEgW2RlZmF1bHQgPSA0MV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRJbnQzMigpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDEwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIFNpbmd1bGFyIHdpdGggZGVmYXVsdHMKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlZmF1bHRfaW50MzIgPSA2MSBbZGVmYXVsdCA9IDQxXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRJbnQzMi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXREZWZhdWx0SW50MzIoKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRJbnQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIFNpbmd1bGFyIHdpdGggZGVmYXVsdHMKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlZmF1bHRfaW50MzIgPSA2MSBbZGVmYXVsdCA9IDQxXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdEludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdEludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0SW50MzJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMTAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBTaW5ndWxhciB3aXRoIGRlZmF1bHRzCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWZhdWx0X2ludDMyID0gNjEgW2RlZmF1bHQgPSA0MV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRJbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDEwMDAwMCk7CiAgICAgICAgZGVmYXVsdEludDMyXyA9IDQxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGxvbmcgZGVmYXVsdEludDY0XyA9IDQyTDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGRlZmF1bHRfaW50NjQgPSA2MiBbZGVmYXVsdCA9IDQyXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEludDY0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEludDY0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMjAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgZGVmYXVsdF9pbnQ2NCA9IDYyIFtkZWZhdWx0ID0gNDJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdEludDY0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXREZWZhdWx0SW50NjQoKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRJbnQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGRlZmF1bHRfaW50NjQgPSA2MiBbZGVmYXVsdCA9IDQyXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdEludDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdEludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdEludDY0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDIwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgZGVmYXVsdF9pbnQ2NCA9IDYyIFtkZWZhdWx0ID0gNDJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0SW50NjQoKSB7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAyMDAwMDApOwogICAgICAgIGRlZmF1bHRJbnQ2NF8gPSA0Mkw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGRlZmF1bHRVaW50MzJfID0gNDM7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgZGVmYXVsdF91aW50MzIgPSA2MyBbZGVmYXVsdCA9IDQzXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFVpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRVaW50MzIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDA0MDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgZGVmYXVsdF91aW50MzIgPSA2MyBbZGVmYXVsdCA9IDQzXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRVaW50MzIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RGVmYXVsdFVpbnQzMigpIHsKICAgICAgICByZXR1cm4gZGVmYXVsdFVpbnQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBkZWZhdWx0X3VpbnQzMiA9IDYzIFtkZWZhdWx0ID0gNDNdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0VWludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdFVpbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdFVpbnQzMl8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDA0MDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBkZWZhdWx0X3VpbnQzMiA9IDYzIFtkZWZhdWx0ID0gNDNdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0VWludDMyKCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwNDAwMDAwKTsKICAgICAgICBkZWZhdWx0VWludDMyXyA9IDQzOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGxvbmcgZGVmYXVsdFVpbnQ2NF8gPSA0NEw7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50NjQgZGVmYXVsdF91aW50NjQgPSA2NCBbZGVmYXVsdCA9IDQ0XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFVpbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRVaW50NjQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDA4MDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50NjQgZGVmYXVsdF91aW50NjQgPSA2NCBbZGVmYXVsdCA9IDQ0XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRVaW50NjQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldERlZmF1bHRVaW50NjQoKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRVaW50NjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50NjQgZGVmYXVsdF91aW50NjQgPSA2NCBbZGVmYXVsdCA9IDQ0XTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdFVpbnQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRVaW50NjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0VWludDY0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDgwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IGRlZmF1bHRfdWludDY0ID0gNjQgW2RlZmF1bHQgPSA0NF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRVaW50NjQoKSB7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDA4MDAwMDApOwogICAgICAgIGRlZmF1bHRVaW50NjRfID0gNDRMOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBkZWZhdWx0U2ludDMyXyA9IC00NTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQzMiBkZWZhdWx0X3NpbnQzMiA9IDY1IFtkZWZhdWx0ID0gLTQ1XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFNpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTaW50MzIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDEwMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgZGVmYXVsdF9zaW50MzIgPSA2NSBbZGVmYXVsdCA9IC00NV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U2ludDMyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldERlZmF1bHRTaW50MzIoKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRTaW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgZGVmYXVsdF9zaW50MzIgPSA2NSBbZGVmYXVsdCA9IC00NV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRTaW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0U2ludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0U2ludDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMTAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIGRlZmF1bHRfc2ludDMyID0gNjUgW2RlZmF1bHQgPSAtNDVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0U2ludDMyKCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAxMDAwMDAwKTsKICAgICAgICBkZWZhdWx0U2ludDMyXyA9IC00NTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBsb25nIGRlZmF1bHRTaW50NjRfID0gNDZMOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IGRlZmF1bHRfc2ludDY0ID0gNjYgW2RlZmF1bHQgPSA0Nl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTaW50NjQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0U2ludDY0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAyMDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IGRlZmF1bHRfc2ludDY0ID0gNjYgW2RlZmF1bHQgPSA0Nl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U2ludDY0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXREZWZhdWx0U2ludDY0KCkgewogICAgICAgIHJldHVybiBkZWZhdWx0U2ludDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IGRlZmF1bHRfc2ludDY0ID0gNjYgW2RlZmF1bHQgPSA0Nl07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRTaW50NjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0U2ludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdFNpbnQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDIwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBkZWZhdWx0X3NpbnQ2NCA9IDY2IFtkZWZhdWx0ID0gNDZdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0U2ludDY0KCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAyMDAwMDAwKTsKICAgICAgICBkZWZhdWx0U2ludDY0XyA9IDQ2TDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZGVmYXVsdEZpeGVkMzJfID0gNDc7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIGRlZmF1bHRfZml4ZWQzMiA9IDY3IFtkZWZhdWx0ID0gNDddOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Rml4ZWQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRGaXhlZDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDA0MDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBkZWZhdWx0X2ZpeGVkMzIgPSA2NyBbZGVmYXVsdCA9IDQ3XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGaXhlZDMyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldERlZmF1bHRGaXhlZDMyKCkgewogICAgICAgIHJldHVybiBkZWZhdWx0Rml4ZWQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkMzIgZGVmYXVsdF9maXhlZDMyID0gNjcgW2RlZmF1bHQgPSA0N107PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRGaXhlZDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdEZpeGVkMzIoaW50IHZhbHVlKSB7CgogICAgICAgIGRlZmF1bHRGaXhlZDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwNDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBkZWZhdWx0X2ZpeGVkMzIgPSA2NyBbZGVmYXVsdCA9IDQ3XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdEZpeGVkMzIoKSB7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDQwMDAwMDApOwogICAgICAgIGRlZmF1bHRGaXhlZDMyXyA9IDQ3OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGxvbmcgZGVmYXVsdEZpeGVkNjRfID0gNDhMOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQ2NCBkZWZhdWx0X2ZpeGVkNjQgPSA2OCBbZGVmYXVsdCA9IDQ4XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Rml4ZWQ2NCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwODAwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgZGVmYXVsdF9maXhlZDY0ID0gNjggW2RlZmF1bHQgPSA0OF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Rml4ZWQ2NC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0RGVmYXVsdEZpeGVkNjQoKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRGaXhlZDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQ2NCBkZWZhdWx0X2ZpeGVkNjQgPSA2OCBbZGVmYXVsdCA9IDQ4XTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdEZpeGVkNjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0Rml4ZWQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIGRlZmF1bHRGaXhlZDY0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwODAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQ2NCBkZWZhdWx0X2ZpeGVkNjQgPSA2OCBbZGVmYXVsdCA9IDQ4XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdEZpeGVkNjQoKSB7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDgwMDAwMDApOwogICAgICAgIGRlZmF1bHRGaXhlZDY0XyA9IDQ4TDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZGVmYXVsdFNmaXhlZDMyXyA9IDQ5OwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgZGVmYXVsdF9zZml4ZWQzMiA9IDY5IFtkZWZhdWx0ID0gNDldOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U2ZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0U2ZpeGVkMzIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MTAwMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQzMiBkZWZhdWx0X3NmaXhlZDMyID0gNjkgW2RlZmF1bHQgPSA0OV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U2ZpeGVkMzIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RGVmYXVsdFNmaXhlZDMyKCkgewogICAgICAgIHJldHVybiBkZWZhdWx0U2ZpeGVkMzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQzMiBkZWZhdWx0X3NmaXhlZDMyID0gNjkgW2RlZmF1bHQgPSA0OV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRTZml4ZWQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRTZml4ZWQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdFNmaXhlZDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgxMDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgZGVmYXVsdF9zZml4ZWQzMiA9IDY5IFtkZWZhdWx0ID0gNDldOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0U2ZpeGVkMzIoKSB7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MTAwMDAwMDApOwogICAgICAgIGRlZmF1bHRTZml4ZWQzMl8gPSA0OTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBsb25nIGRlZmF1bHRTZml4ZWQ2NF8gPSAtNTBMOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgZGVmYXVsdF9zZml4ZWQ2NCA9IDcwIFtkZWZhdWx0ID0gLTUwXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFNmaXhlZDY0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdFNmaXhlZDY0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDIwMDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgZGVmYXVsdF9zZml4ZWQ2NCA9IDcwIFtkZWZhdWx0ID0gLTUwXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTZml4ZWQ2NC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0RGVmYXVsdFNmaXhlZDY0KCkgewogICAgICAgIHJldHVybiBkZWZhdWx0U2ZpeGVkNjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBkZWZhdWx0X3NmaXhlZDY0ID0gNzAgW2RlZmF1bHQgPSAtNTBdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0U2ZpeGVkNjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0U2ZpeGVkNjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0U2ZpeGVkNjRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDIwMDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBkZWZhdWx0X3NmaXhlZDY0ID0gNzAgW2RlZmF1bHQgPSAtNTBdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0U2ZpeGVkNjQoKSB7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MjAwMDAwMDApOwogICAgICAgIGRlZmF1bHRTZml4ZWQ2NF8gPSAtNTBMOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGZsb2F0IGRlZmF1bHRGbG9hdF8gPSA1MS41RjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IGRlZmF1bHRfZmxvYXQgPSA3MSBbZGVmYXVsdCA9IDUxLjVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0RmxvYXQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0RmxvYXQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4NDAwMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmbG9hdCBkZWZhdWx0X2Zsb2F0ID0gNzEgW2RlZmF1bHQgPSA1MS41XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGbG9hdC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZsb2F0IGdldERlZmF1bHRGbG9hdCgpIHsKICAgICAgICByZXR1cm4gZGVmYXVsdEZsb2F0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgZGVmYXVsdF9mbG9hdCA9IDcxIFtkZWZhdWx0ID0gNTEuNV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRGbG9hdCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRGbG9hdChmbG9hdCB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0RmxvYXRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDQwMDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmbG9hdCBkZWZhdWx0X2Zsb2F0ID0gNzEgW2RlZmF1bHQgPSA1MS41XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdEZsb2F0KCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDQwMDAwMDAwKTsKICAgICAgICBkZWZhdWx0RmxvYXRfID0gNTEuNUY7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgZG91YmxlIGRlZmF1bHREb3VibGVfID0gNTIwMDBEOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIGRlZmF1bHRfZG91YmxlID0gNzIgW2RlZmF1bHQgPSA1MjAwMF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHREb3VibGUgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0RG91YmxlKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDgwMDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIGRlZmF1bHRfZG91YmxlID0gNzIgW2RlZmF1bHQgPSA1MjAwMF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0RG91YmxlLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZG91YmxlIGdldERlZmF1bHREb3VibGUoKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHREb3VibGVfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgZGVmYXVsdF9kb3VibGUgPSA3MiBbZGVmYXVsdCA9IDUyMDAwXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdERvdWJsZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHREb3VibGUoZG91YmxlIHZhbHVlKSB7CgogICAgICAgIGRlZmF1bHREb3VibGVfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDgwMDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgZGVmYXVsdF9kb3VibGUgPSA3MiBbZGVmYXVsdCA9IDUyMDAwXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdERvdWJsZSgpIHsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHg4MDAwMDAwMCk7CiAgICAgICAgZGVmYXVsdERvdWJsZV8gPSA1MjAwMEQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgYm9vbGVhbiBkZWZhdWx0Qm9vbF8gPSB0cnVlOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBkZWZhdWx0X2Jvb2wgPSA3MyBbZGVmYXVsdCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Qm9vbCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRCb29sKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMl8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBkZWZhdWx0X2Jvb2wgPSA3MyBbZGVmYXVsdCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdEJvb2wuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGdldERlZmF1bHRCb29sKCkgewogICAgICAgIHJldHVybiBkZWZhdWx0Qm9vbF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgZGVmYXVsdF9ib29sID0gNzMgW2RlZmF1bHQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdEJvb2wgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0Qm9vbChib29sZWFuIHZhbHVlKSB7CgogICAgICAgIGRlZmF1bHRCb29sXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBkZWZhdWx0X2Jvb2wgPSA3MyBbZGVmYXVsdCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0Qm9vbCgpIHsKICAgICAgICBiaXRGaWVsZDJfID0gKGJpdEZpZWxkMl8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgZGVmYXVsdEJvb2xfID0gdHJ1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLmxhbmcuT2JqZWN0IGRlZmF1bHRTdHJpbmdfID0gImhlbGxvIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZyA9IDc0IFtkZWZhdWx0ID0gImhlbGxvIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdFN0cmluZygpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDJfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZyA9IDc0IFtkZWZhdWx0ID0gImhlbGxvIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U3RyaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdFN0cmluZygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlZmF1bHRTdHJpbmdfOwogICAgICAgIGlmICghKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPQogICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgICAgZGVmYXVsdFN0cmluZ18gPSBzOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBkZWZhdWx0U3RyaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0RGVmYXVsdFN0cmluZ0J5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVmYXVsdFN0cmluZ187CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIGRlZmF1bHRTdHJpbmdfID0gYjsKICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdFN0cmluZyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBkZWZhdWx0U3RyaW5nXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdFN0cmluZygpIHsKICAgICAgICBkZWZhdWx0U3RyaW5nXyA9IGdldERlZmF1bHRJbnN0YW5jZSgpLmdldERlZmF1bHRTdHJpbmcoKTsKICAgICAgICBiaXRGaWVsZDJfID0gKGJpdEZpZWxkMl8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZyA9IDc0IFtkZWZhdWx0ID0gImhlbGxvIl07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIGZvciBkZWZhdWx0U3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdFN0cmluZ0J5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBkZWZhdWx0U3RyaW5nXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGVmYXVsdEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoIndvcmxkIik7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBkZWZhdWx0X2J5dGVzID0gNzUgW2RlZmF1bHQgPSAid29ybGQiXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEJ5dGVzKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMl8gJiAweDAwMDAwMDA0KSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgZGVmYXVsdF9ieXRlcyA9IDc1IFtkZWZhdWx0ID0gIndvcmxkIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Qnl0ZXMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0RGVmYXVsdEJ5dGVzKCkgewogICAgICAgIHJldHVybiBkZWZhdWx0Qnl0ZXNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBkZWZhdWx0X2J5dGVzID0gNzUgW2RlZmF1bHQgPSAid29ybGQiXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdEJ5dGVzIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdEJ5dGVzKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZGVmYXVsdEJ5dGVzXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgZGVmYXVsdF9ieXRlcyA9IDc1IFtkZWZhdWx0ID0gIndvcmxkIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRCeXRlcygpIHsKICAgICAgICBiaXRGaWVsZDJfID0gKGJpdEZpZWxkMl8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgZGVmYXVsdEJ5dGVzXyA9IGdldERlZmF1bHRJbnN0YW5jZSgpLmdldERlZmF1bHRCeXRlcygpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBkZWZhdWx0TmVzdGVkRW51bV8gPSAyOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gZGVmYXVsdF9uZXN0ZWRfZW51bSA9IDgxIFtkZWZhdWx0ID0gQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdE5lc3RlZEVudW0gZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0TmVzdGVkRW51bSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDJfICYgMHgwMDAwMDAwOCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGRlZmF1bHRfbmVzdGVkX2VudW0gPSA4MSBbZGVmYXVsdCA9IEJBUl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0TmVzdGVkRW51bS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBnZXREZWZhdWx0TmVzdGVkRW51bSgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLmZvck51bWJlcihkZWZhdWx0TmVzdGVkRW51bV8pOwogICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5CQVIgOiByZXN1bHQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGRlZmF1bHRfbmVzdGVkX2VudW0gPSA4MSBbZGVmYXVsdCA9IEJBUl07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHROZXN0ZWRFbnVtIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdE5lc3RlZEVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgZGVmYXVsdE5lc3RlZEVudW1fID0gdmFsdWUuZ2V0TnVtYmVyKCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGRlZmF1bHRfbmVzdGVkX2VudW0gPSA4MSBbZGVmYXVsdCA9IEJBUl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHROZXN0ZWRFbnVtKCkgewogICAgICAgIGJpdEZpZWxkMl8gPSAoYml0RmllbGQyXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICBkZWZhdWx0TmVzdGVkRW51bV8gPSAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBkZWZhdWx0Rm9yZWlnbkVudW1fID0gNTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIGRlZmF1bHRfZm9yZWlnbl9lbnVtID0gODIgW2RlZmF1bHQgPSBGT1JFSUdOX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZvcmVpZ25FbnVtIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEZvcmVpZ25FbnVtKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMl8gJiAweDAwMDAwMDEwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdEZvcmVpZ25FbnVtLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldERlZmF1bHRGb3JlaWduRW51bSgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcihkZWZhdWx0Rm9yZWlnbkVudW1fKTsKICAgICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuRk9SRUlHTl9MSVRFX0JBUiA6IHJlc3VsdDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0Rm9yZWlnbkVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0Rm9yZWlnbkVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgZGVmYXVsdEZvcmVpZ25FbnVtXyA9IHZhbHVlLmdldE51bWJlcigpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBkZWZhdWx0X2ZvcmVpZ25fZW51bSA9IDgyIFtkZWZhdWx0ID0gRk9SRUlHTl9MSVRFX0JBUl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRGb3JlaWduRW51bSgpIHsKICAgICAgICBiaXRGaWVsZDJfID0gKGJpdEZpZWxkMl8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgZGVmYXVsdEZvcmVpZ25FbnVtXyA9IDU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGRlZmF1bHRJbXBvcnRFbnVtXyA9IDg7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIGRlZmF1bHRfaW1wb3J0X2VudW0gPSA4MyBbZGVmYXVsdCA9IElNUE9SVF9MSVRFX0JBUl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRJbXBvcnRFbnVtIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEltcG9ydEVudW0oKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQyXyAmIDB4MDAwMDAwMjApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIGRlZmF1bHRfaW1wb3J0X2VudW0gPSA4MyBbZGVmYXVsdCA9IElNUE9SVF9MSVRFX0JBUl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0SW1wb3J0RW51bS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIGdldERlZmF1bHRJbXBvcnRFbnVtKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLmZvck51bWJlcihkZWZhdWx0SW1wb3J0RW51bV8pOwogICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLklNUE9SVF9MSVRFX0JBUiA6IHJlc3VsdDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBkZWZhdWx0X2ltcG9ydF9lbnVtID0gODMgW2RlZmF1bHQgPSBJTVBPUlRfTElURV9CQVJdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0SW1wb3J0RW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRJbXBvcnRFbnVtKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgZGVmYXVsdEltcG9ydEVudW1fID0gdmFsdWUuZ2V0TnVtYmVyKCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgZGVmYXVsdF9pbXBvcnRfZW51bSA9IDgzIFtkZWZhdWx0ID0gSU1QT1JUX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdEltcG9ydEVudW0oKSB7CiAgICAgICAgYml0RmllbGQyXyA9IChiaXRGaWVsZDJfICYgfjB4MDAwMDAwMjApOwogICAgICAgIGRlZmF1bHRJbXBvcnRFbnVtXyA9IDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBkZWZhdWx0U3RyaW5nUGllY2VfID0gImFiYyI7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmdfcGllY2UgPSA4NCBbZGVmYXVsdCA9ICJhYmMiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTdHJpbmdQaWVjZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0U3RyaW5nUGllY2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQyXyAmIDB4MDAwMDAwNDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmdfcGllY2UgPSA4NCBbZGVmYXVsdCA9ICJhYmMiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U3RyaW5nUGllY2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXREZWZhdWx0U3RyaW5nUGllY2UoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0U3RyaW5nUGllY2VfOwogICAgICAgIGlmICghKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPQogICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgICAgZGVmYXVsdFN0cmluZ1BpZWNlXyA9IHM7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmdfcGllY2UgPSA4NCBbZGVmYXVsdCA9ICJhYmMiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVmYXVsdFN0cmluZ1BpZWNlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0RGVmYXVsdFN0cmluZ1BpZWNlQnl0ZXMoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0U3RyaW5nUGllY2VfOwogICAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBTdHJpbmcpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gYjsKICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nX3BpZWNlID0gODQgW2RlZmF1bHQgPSAiYWJjIiwgY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0U3RyaW5nUGllY2UgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0U3RyaW5nUGllY2UoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDQwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmdfcGllY2UgPSA4NCBbZGVmYXVsdCA9ICJhYmMiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRTdHJpbmdQaWVjZSgpIHsKICAgICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0RGVmYXVsdFN0cmluZ1BpZWNlKCk7CiAgICAgICAgYml0RmllbGQyXyA9IChiaXRGaWVsZDJfICYgfjB4MDAwMDAwNDApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmdfcGllY2UgPSA4NCBbZGVmYXVsdCA9ICJhYmMiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIGZvciBkZWZhdWx0U3RyaW5nUGllY2UgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0U3RyaW5nUGllY2VCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZGVmYXVsdFN0cmluZ1BpZWNlXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLmxhbmcuT2JqZWN0IGRlZmF1bHRDb3JkXyA9ICIxMjMiOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRDb3JkIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRDb3JkKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMl8gJiAweDAwMDAwMDgwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Q29yZC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldERlZmF1bHRDb3JkKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVmYXVsdENvcmRfOwogICAgICAgIGlmICghKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPQogICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgICAgZGVmYXVsdENvcmRfID0gczsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X2NvcmQgPSA4NSBbZGVmYXVsdCA9ICIxMjMiLCBjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlZmF1bHRDb3JkLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0RGVmYXVsdENvcmRCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlZmF1bHRDb3JkXzsKICAgICAgICBpZiAocmVmIGluc3RhbmNlb2YgU3RyaW5nKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgICAgZGVmYXVsdENvcmRfID0gYjsKICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRDb3JkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdENvcmQoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBkZWZhdWx0Q29yZF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X2NvcmQgPSA4NSBbZGVmYXVsdCA9ICIxMjMiLCBjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0Q29yZCgpIHsKICAgICAgICBkZWZhdWx0Q29yZF8gPSBnZXREZWZhdWx0SW5zdGFuY2UoKS5nZXREZWZhdWx0Q29yZCgpOwogICAgICAgIGJpdEZpZWxkMl8gPSAoYml0RmllbGQyXyAmIH4weDAwMDAwMDgwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIGZvciBkZWZhdWx0Q29yZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRDb3JkQnl0ZXMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGRlZmF1bHRDb3JkXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSAxMTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mVWludDMyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mVWludDMyKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTExOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gMTExOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZVaW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldE9uZW9mVWludDMyKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTExKSB7CiAgICAgICAgICByZXR1cm4gKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSAxMTE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mVWludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZVaW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMTsKICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gMTExOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlVpbnQzMigpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMSkgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiBvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX25lc3RlZF9tZXNzYWdlID0gMTEyOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZk5lc3RlZE1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZk5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxMTI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX25lc3RlZF9tZXNzYWdlID0gMTEyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZOZXN0ZWRNZXNzYWdlLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9uZW9mTmVzdGVkTWVzc2FnZSgpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIpIHsKICAgICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIpIHsKICAgICAgICAgICAgcmV0dXJuIG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZk5lc3RlZE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTEyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZk5lc3RlZE1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTEyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZU9uZW9mTmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIgJiYKICAgICAgICAgICAgICBvbmVvZkZpZWxkXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UubmV3QnVpbGRlcigoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXykKICAgICAgICAgICAgICAgIC5tZXJnZUZyb20odmFsdWUpLmJ1aWxkUGFydGlhbCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMikgewogICAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZk5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEyKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEyKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICAgIGlmICgob25lb2ZGaWVsZENhc2VfID09IDExMikgJiYgKG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpKSB7CiAgICAgICAgICByZXR1cm4gb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMikgewogICAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF87CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9uZW9mTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCEob25lb2ZGaWVsZENhc2VfID09IDExMikpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlN0cmluZygpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDExMzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMykgewogICAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gczsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYjsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN0cmluZygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMzsKICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlN0cmluZygpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMykgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZTdHJpbmdCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTEzOwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDExNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTE0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDExNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mQnl0ZXMuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXMoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTQpIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSAxMTQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mQnl0ZXMgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZkJ5dGVzKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTE0OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gMTE0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkJ5dGVzKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE0KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX2xhenlfbmVzdGVkX21lc3NhZ2UgPSAxMTUgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxMTU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX2xhenlfbmVzdGVkX21lc3NhZ2UgPSAxMTUgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZSgpIHsKICAgICAgICBpZiAob25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXzsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgICAgIHJldHVybiBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX2xhenlfbmVzdGVkX21lc3NhZ2UgPSAxMTUgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTE1OwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9sYXp5X25lc3RlZF9tZXNzYWdlID0gMTE1IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExNTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT25lb2ZMYXp5TmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1ICYmCiAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLm5ld0J1aWxkZXIoKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF8pCiAgICAgICAgICAgICAgICAubWVyZ2VGcm9tKHZhbHVlKS5idWlsZFBhcnRpYWwoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUpIHsKICAgICAgICAgICAgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExNTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZMYXp5TmVzdGVkTWVzc2FnZSgpIHsKICAgICAgICBpZiAob25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBnZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICAgIGlmICgob25lb2ZGaWVsZENhc2VfID09IDExNSkgJiYgKG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSkgewogICAgICAgICAgcmV0dXJuIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXzsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9sYXp5X25lc3RlZF9tZXNzYWdlID0gMTE1IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoIShvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSkgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyPiBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZk5lc3RlZE1lc3NhZ2UyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZOZXN0ZWRNZXNzYWdlMigpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDExNzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG9uZW9mX25lc3RlZF9tZXNzYWdlMiA9IDExNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mTmVzdGVkTWVzc2FnZTIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIGdldE9uZW9mTmVzdGVkTWVzc2FnZTIoKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNykgewogICAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpIG9uZW9mRmllbGRfOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSB7CiAgICAgICAgICAgIHJldHVybiBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mTmVzdGVkTWVzc2FnZTIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiB2YWx1ZSkgewogICAgICAgIGlmIChvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTE3OwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mTmVzdGVkTWVzc2FnZTIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTE3OwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT25lb2ZOZXN0ZWRNZXNzYWdlMihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNyAmJgogICAgICAgICAgICAgIG9uZW9mRmllbGRfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLm5ld0J1aWxkZXIoKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpIG9uZW9mRmllbGRfKQogICAgICAgICAgICAgICAgLm1lcmdlRnJvbSh2YWx1ZSkuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSB7CiAgICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlMkJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTc7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZk5lc3RlZE1lc3NhZ2UyKCkgewogICAgICAgIGlmIChvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTcpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTcpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlMkJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLkJ1aWxkZXIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlMkJ1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIGdldE9uZW9mTmVzdGVkTWVzc2FnZTJGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMk9yQnVpbGRlciBnZXRPbmVvZk5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyKCkgewogICAgICAgIGlmICgob25lb2ZGaWVsZENhc2VfID09IDExNykgJiYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyAhPSBudWxsKSkgewogICAgICAgICAgcmV0dXJuIG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSB7CiAgICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikgb25lb2ZGaWVsZF87CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9uZW9mTmVzdGVkTWVzc2FnZTJGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoIShvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSkgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTJPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikgb25lb2ZGaWVsZF8sCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExNzsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gb25lb2ZOZXN0ZWRNZXNzYWdlMkJ1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBkZWNlcHRpdmVseU5hbWVkTGlzdF8gOwogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogVGVzdHMgdG9TdHJpbmcgZm9yIG5vbi1yZXBlYXRlZCBmaWVsZHMgd2l0aCBhIGxpc3Qgc3VmZml4CiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWNlcHRpdmVseV9uYW1lZF9saXN0ID0gMTE2OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlY2VwdGl2ZWx5TmFtZWRMaXN0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMl8gJiAweDAwMDA0MDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogVGVzdHMgdG9TdHJpbmcgZm9yIG5vbi1yZXBlYXRlZCBmaWVsZHMgd2l0aCBhIGxpc3Qgc3VmZml4CiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWNlcHRpdmVseV9uYW1lZF9saXN0ID0gMTE2OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVjZXB0aXZlbHlOYW1lZExpc3QuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RGVjZXB0aXZlbHlOYW1lZExpc3QoKSB7CiAgICAgICAgcmV0dXJuIGRlY2VwdGl2ZWx5TmFtZWRMaXN0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogVGVzdHMgdG9TdHJpbmcgZm9yIG5vbi1yZXBlYXRlZCBmaWVsZHMgd2l0aCBhIGxpc3Qgc3VmZml4CiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWNlcHRpdmVseV9uYW1lZF9saXN0ID0gMTE2OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlY2VwdGl2ZWx5TmFtZWRMaXN0KGludCB2YWx1ZSkgewoKICAgICAgICBkZWNlcHRpdmVseU5hbWVkTGlzdF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIFRlc3RzIHRvU3RyaW5nIGZvciBub24tcmVwZWF0ZWQgZmllbGRzIHdpdGggYSBsaXN0IHN1ZmZpeAogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVjZXB0aXZlbHlfbmFtZWRfbGlzdCA9IDExNjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVjZXB0aXZlbHlOYW1lZExpc3QoKSB7CiAgICAgICAgYml0RmllbGQyXyA9IChiaXRGaWVsZDJfICYgfjB4MDAwMDQwMDApOwogICAgICAgIGRlY2VwdGl2ZWx5TmFtZWRMaXN0XyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEFsbFR5cGVzTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0QWxsVHlwZXNMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RBbGxUeXBlc0xpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEFsbFR5cGVzTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIEZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBjIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNDKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGMuCiAgICAgKi8KICAgIGludCBnZXRDKCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBGb3JlaWduTWVzc2FnZUxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSkKICAgICAgRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBGb3JlaWduTWVzc2FnZUxpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgRm9yZWlnbk1lc3NhZ2VMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgRm9yZWlnbk1lc3NhZ2VMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IEZvcmVpZ25NZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgQ19GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBpbnQgY18gPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNDKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0QygpIHsKICAgICAgcmV0dXJuIGNfOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMSwgY18pOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDEsIGNfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUpIG9iajsKCiAgICAgIGlmIChoYXNDKCkgIT0gb3RoZXIuaGFzQygpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNDKCkpIHsKICAgICAgICBpZiAoZ2V0QygpCiAgICAgICAgICAgICE9IG90aGVyLmdldEMoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0MoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIENfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEMoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBjXyA9IDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5jXyA9IGNfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKG90aGVyLmhhc0MoKSkgewogICAgICAgICAgc2V0QyhvdGhlci5nZXRDKCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIGNfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGludCBjXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0MoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0QygpIHsKICAgICAgICByZXR1cm4gY187CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGMgPSAxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBjIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0QyhpbnQgdmFsdWUpIHsKCiAgICAgICAgY18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGMgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJDKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBjXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPEZvcmVpZ25NZXNzYWdlTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxGb3JlaWduTWVzc2FnZUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBGb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxGb3JlaWduTWVzc2FnZUxpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8Rm9yZWlnbk1lc3NhZ2VMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0UGFja2VkVHlwZXNMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkVHlwZXNMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gOTAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UGFja2VkSW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRJbnQzMi4KICAgICAqLwogICAgaW50IGdldFBhY2tlZEludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gOTAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkSW50MzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRJbnQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFBhY2tlZEludDY0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCBwYWNrZWRfaW50NjQgPSA5MSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkSW50NjQuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRJbnQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgbG9uZyBnZXRQYWNrZWRJbnQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHBhY2tlZF91aW50MzIgPSA5MiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkVWludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UGFja2VkVWludDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRVaW50MzIuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRVaW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFVpbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRVaW50MzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCBwYWNrZWRfdWludDY0ID0gOTMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFVpbnQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFBhY2tlZFVpbnQ2NExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkVWludDY0LgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkVWludDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRVaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBsb25nIGdldFBhY2tlZFVpbnQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHBhY2tlZF9zaW50MzIgPSA5NCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkU2ludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UGFja2VkU2ludDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRTaW50MzIuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRTaW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFNpbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRTaW50MzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCBwYWNrZWRfc2ludDY0ID0gOTUgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFNpbnQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFBhY2tlZFNpbnQ2NExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHBhY2tlZF9zaW50NjQgPSA5NSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkU2ludDY0LgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkU2ludDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHBhY2tlZF9zaW50NjQgPSA5NSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRTaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBsb25nIGdldFBhY2tlZFNpbnQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRGaXhlZDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UGFja2VkRml4ZWQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRGaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkRml4ZWQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcGFja2VkX2ZpeGVkMzIgPSA5NiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRGaXhlZDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFBhY2tlZEZpeGVkMzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkRml4ZWQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFBhY2tlZEZpeGVkNjRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkRml4ZWQ2NC4KICAgICAqLwogICAgaW50IGdldFBhY2tlZEZpeGVkNjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHBhY2tlZF9maXhlZDY0ID0gOTcgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkRml4ZWQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGxvbmcgZ2V0UGFja2VkRml4ZWQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcGFja2VkX3NmaXhlZDMyID0gOTggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFNmaXhlZDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UGFja2VkU2ZpeGVkMzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRTZml4ZWQzMi4KICAgICAqLwogICAgaW50IGdldFBhY2tlZFNmaXhlZDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcGFja2VkX3NmaXhlZDMyID0gOTggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkU2ZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkU2ZpeGVkMzIoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTZml4ZWQ2NC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+IGdldFBhY2tlZFNmaXhlZDY0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCBwYWNrZWRfc2ZpeGVkNjQgPSA5OSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkU2ZpeGVkNjQuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRTZml4ZWQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFNmaXhlZDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgbG9uZyBnZXRQYWNrZWRTZml4ZWQ2NChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcGFja2VkX2Zsb2F0ID0gMTAwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRGbG9hdC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkZsb2F0PiBnZXRQYWNrZWRGbG9hdExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcGFja2VkX2Zsb2F0ID0gMTAwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRGbG9hdC4KICAgICAqLwogICAgaW50IGdldFBhY2tlZEZsb2F0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcGFja2VkX2Zsb2F0ID0gMTAwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEZsb2F0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgZmxvYXQgZ2V0UGFja2VkRmxvYXQoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSBwYWNrZWRfZG91YmxlID0gMTAxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWREb3VibGUuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Eb3VibGU+IGdldFBhY2tlZERvdWJsZUxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZERvdWJsZS4KICAgICAqLwogICAgaW50IGdldFBhY2tlZERvdWJsZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSBwYWNrZWRfZG91YmxlID0gMTAxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZERvdWJsZSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGRvdWJsZSBnZXRQYWNrZWREb3VibGUoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEJvb2wuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Cb29sZWFuPiBnZXRQYWNrZWRCb29sTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHBhY2tlZF9ib29sID0gMTAyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRCb29sLgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkQm9vbENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkQm9vbCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGJvb2xlYW4gZ2V0UGFja2VkQm9vbChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEVudW0uCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZT4gZ2V0UGFja2VkRW51bUxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEVudW0uCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRFbnVtQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkRW51bSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRQYWNrZWRFbnVtKGludCBpbmRleCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkVHlwZXNMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdFBhY2tlZFR5cGVzTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZFR5cGVzTGl0ZSkKICAgICAgVGVzdFBhY2tlZFR5cGVzTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdFBhY2tlZFR5cGVzTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0UGFja2VkVHlwZXNMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdFBhY2tlZFR5cGVzTGl0ZSgpIHsKICAgICAgcGFja2VkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHBhY2tlZEludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgcGFja2VkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwYWNrZWRVaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwYWNrZWRTaW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHBhY2tlZFNpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHBhY2tlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHBhY2tlZEZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwYWNrZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcGFja2VkU2ZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwYWNrZWRGbG9hdF8gPSBlbXB0eUZsb2F0TGlzdCgpOwogICAgICBwYWNrZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgIHBhY2tlZEJvb2xfID0gZW1wdHlCb29sZWFuTGlzdCgpOwogICAgICBwYWNrZWRFbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0UGFja2VkVHlwZXNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfSU5UMzJfRklFTERfTlVNQkVSID0gOTA7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZEludDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRJbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFBhY2tlZEludDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gOTAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEludDMyLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZEludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRJbnQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA5MCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkSW50MzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZEludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9JTlQ2NF9GSUVMRF9OVU1CRVIgPSA5MTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHBhY2tlZEludDY0XyA9CiAgICAgICAgZW1wdHlMb25nTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCBwYWNrZWRfaW50NjQgPSA5MSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkSW50NjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICBnZXRQYWNrZWRJbnQ2NExpc3QoKSB7CiAgICAgIHJldHVybiBwYWNrZWRJbnQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRJbnQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkSW50NjRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkSW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgbG9uZyBnZXRQYWNrZWRJbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEludDY0Xy5nZXRMb25nKGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZEludDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9VSU5UMzJfRklFTERfTlVNQkVSID0gOTI7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZFVpbnQzMl8gPQogICAgICAgIGVtcHR5SW50TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRVaW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRQYWNrZWRVaW50MzJMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkVWludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHBhY2tlZF91aW50MzIgPSA5MiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkVWludDMyLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZFVpbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkVWludDMyXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkVWludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRVaW50MzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRVaW50MzJfLmdldEludChpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRVaW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1VJTlQ2NF9GSUVMRF9OVU1CRVIgPSA5MzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHBhY2tlZFVpbnQ2NF8gPQogICAgICAgIGVtcHR5TG9uZ0xpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkVWludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgZ2V0UGFja2VkVWludDY0TGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFVpbnQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCBwYWNrZWRfdWludDY0ID0gOTMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFVpbnQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRVaW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFVpbnQ2NF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFVpbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBsb25nIGdldFBhY2tlZFVpbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFVpbnQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRVaW50NjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1NJTlQzMl9GSUVMRF9OVU1CRVIgPSA5NDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkU2ludDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiBwYWNrZWRfc2ludDMyID0gOTQgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFNpbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFBhY2tlZFNpbnQzMkxpc3QoKSB7CiAgICAgIHJldHVybiBwYWNrZWRTaW50MzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRTaW50MzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkU2ludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRTaW50MzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHBhY2tlZF9zaW50MzIgPSA5NCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRTaW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZFNpbnQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNpbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZFNpbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfU0lOVDY0X0ZJRUxEX05VTUJFUiA9IDk1OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcGFja2VkU2ludDY0XyA9CiAgICAgICAgZW1wdHlMb25nTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTaW50NjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICBnZXRQYWNrZWRTaW50NjRMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkU2ludDY0XzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHBhY2tlZF9zaW50NjQgPSA5NSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkU2ludDY0LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZFNpbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkU2ludDY0Xy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCBwYWNrZWRfc2ludDY0ID0gOTUgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkU2ludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGxvbmcgZ2V0UGFja2VkU2ludDY0KGludCBpbmRleCkgewogICAgICByZXR1cm4gcGFja2VkU2ludDY0Xy5nZXRMb25nKGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZFNpbnQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfRklYRUQzMl9GSUVMRF9OVU1CRVIgPSA5NjsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkRml4ZWQzMl8gPQogICAgICAgIGVtcHR5SW50TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEZpeGVkMzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRQYWNrZWRGaXhlZDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEZpeGVkMzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEZpeGVkMzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkRml4ZWQzMkNvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkRml4ZWQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkRml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkRml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEZpeGVkMzJfLmdldEludChpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRGaXhlZDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9GSVhFRDY0X0ZJRUxEX05VTUJFUiA9IDk3OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcGFja2VkRml4ZWQ2NF8gPQogICAgICAgIGVtcHR5TG9uZ0xpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRGaXhlZDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgZ2V0UGFja2VkRml4ZWQ2NExpc3QoKSB7CiAgICAgIHJldHVybiBwYWNrZWRGaXhlZDY0XzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRGaXhlZDY0LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZEZpeGVkNjRDb3VudCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEZpeGVkNjRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEZpeGVkNjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgbG9uZyBnZXRQYWNrZWRGaXhlZDY0KGludCBpbmRleCkgewogICAgICByZXR1cm4gcGFja2VkRml4ZWQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRGaXhlZDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9TRklYRUQzMl9GSUVMRF9OVU1CRVIgPSA5ODsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkU2ZpeGVkMzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcGFja2VkX3NmaXhlZDMyID0gOTggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFNmaXhlZDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UGFja2VkU2ZpeGVkMzJMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkU2ZpeGVkMzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiBwYWNrZWRfc2ZpeGVkMzIgPSA5OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkU2ZpeGVkMzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkU2ZpeGVkMzJDb3VudCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNmaXhlZDMyXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFNmaXhlZDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRTZml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNmaXhlZDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkU2ZpeGVkMzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1NGSVhFRDY0X0ZJRUxEX05VTUJFUiA9IDk5OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcGFja2VkU2ZpeGVkNjRfID0KICAgICAgICBlbXB0eUxvbmdMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTZml4ZWQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgIGdldFBhY2tlZFNmaXhlZDY0TGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNmaXhlZDY0XzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNmaXhlZDY0LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZFNmaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQ2NF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCBwYWNrZWRfc2ZpeGVkNjQgPSA5OSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRTZml4ZWQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBsb25nIGdldFBhY2tlZFNmaXhlZDY0KGludCBpbmRleCkgewogICAgICByZXR1cm4gcGFja2VkU2ZpeGVkNjRfLmdldExvbmcoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkU2ZpeGVkNjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0ZMT0FUX0ZJRUxEX05VTUJFUiA9IDEwMDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkZsb2F0TGlzdCBwYWNrZWRGbG9hdF8gPQogICAgICAgIGVtcHR5RmxvYXRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHBhY2tlZF9mbG9hdCA9IDEwMCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkRmxvYXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgZ2V0UGFja2VkRmxvYXRMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkRmxvYXRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEZsb2F0LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZEZsb2F0Q291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRGbG9hdF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkRmxvYXQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgZmxvYXQgZ2V0UGFja2VkRmxvYXQoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRGbG9hdF8uZ2V0RmxvYXQoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkRmxvYXRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0RPVUJMRV9GSUVMRF9OVU1CRVIgPSAxMDE7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Eb3VibGVMaXN0IHBhY2tlZERvdWJsZV8gPQogICAgICAgIGVtcHR5RG91YmxlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcGFja2VkX2RvdWJsZSA9IDEwMSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkRG91YmxlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkRvdWJsZT4KICAgICAgICBnZXRQYWNrZWREb3VibGVMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkRG91YmxlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZERvdWJsZS4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWREb3VibGVDb3VudCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZERvdWJsZV8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcGFja2VkX2RvdWJsZSA9IDEwMSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWREb3VibGUgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgZG91YmxlIGdldFBhY2tlZERvdWJsZShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZERvdWJsZV8uZ2V0RG91YmxlKGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZERvdWJsZU1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfQk9PTF9GSUVMRF9OVU1CRVIgPSAxMDI7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Cb29sZWFuTGlzdCBwYWNrZWRCb29sXyA9CiAgICAgICAgZW1wdHlCb29sZWFuTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHBhY2tlZF9ib29sID0gMTAyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRCb29sLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkJvb2xlYW4+CiAgICAgICAgZ2V0UGFja2VkQm9vbExpc3QoKSB7CiAgICAgIHJldHVybiBwYWNrZWRCb29sXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCBwYWNrZWRfYm9vbCA9IDEwMiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkQm9vbC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRCb29sQ291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRCb29sXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkQm9vbCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBib29sZWFuIGdldFBhY2tlZEJvb2woaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRCb29sXy5nZXRCb29sZWFuKGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZEJvb2xNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0VOVU1fRklFTERfTlVNQkVSID0gMTAzOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBwYWNrZWRFbnVtXzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IHBhY2tlZEVudW1fY29udmVydGVyXyA9CiAgICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+KCkgewogICAgICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgY29udmVydChqYXZhLmxhbmcuSW50ZWdlciBmcm9tKSB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcihmcm9tKTsKICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5GT1JFSUdOX0xJVEVfRk9PIDogcmVzdWx0OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IGdldFBhY2tlZEVudW1MaXN0KCkgewogICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPihwYWNrZWRFbnVtXywgcGFja2VkRW51bV9jb252ZXJ0ZXJfKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkRW51bUNvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkRW51bV8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRQYWNrZWRFbnVtKGludCBpbmRleCkgewogICAgICByZXR1cm4gcGFja2VkRW51bV9jb252ZXJ0ZXJfLmNvbnZlcnQocGFja2VkRW51bV8uZ2V0KGluZGV4KSk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRFbnVtTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZTsKCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIGlmIChnZXRQYWNrZWRJbnQzMkxpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoNzIyKTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhwYWNrZWRJbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkSW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzJOb1RhZyhwYWNrZWRJbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkSW50NjRMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDczMCk7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkSW50NjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZEludDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUludDY0Tm9UYWcocGFja2VkSW50NjRfLmdldExvbmcoaSkpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRVaW50MzJMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDczOCk7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkVWludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRVaW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkVWludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRVaW50NjRMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDc0Nik7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkVWludDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRVaW50NjRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDY0Tm9UYWcocGFja2VkVWludDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkU2ludDMyTGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg3NTQpOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZFNpbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkU2ludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVNJbnQzMk5vVGFnKHBhY2tlZFNpbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkU2ludDY0TGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg3NjIpOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZFNpbnQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkU2ludDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVNJbnQ2NE5vVGFnKHBhY2tlZFNpbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDc3MCk7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkRml4ZWQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkRml4ZWQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVGaXhlZDMyTm9UYWcocGFja2VkRml4ZWQzMl8uZ2V0SW50KGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRml4ZWQ2NExpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoNzc4KTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhwYWNrZWRGaXhlZDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRGaXhlZDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUZpeGVkNjROb1RhZyhwYWNrZWRGaXhlZDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkU2ZpeGVkMzJMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDc4Nik7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkU2ZpeGVkMzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZFNmaXhlZDMyXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVNGaXhlZDMyTm9UYWcocGFja2VkU2ZpeGVkMzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZFNmaXhlZDY0TGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg3OTQpOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZFNmaXhlZDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRTZml4ZWQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVTRml4ZWQ2NE5vVGFnKHBhY2tlZFNmaXhlZDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRmxvYXRMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDgwMik7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkRmxvYXRNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZEZsb2F0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUZsb2F0Tm9UYWcocGFja2VkRmxvYXRfLmdldEZsb2F0KGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRG91YmxlTGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg4MTApOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZERvdWJsZU1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkRG91YmxlXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZURvdWJsZU5vVGFnKHBhY2tlZERvdWJsZV8uZ2V0RG91YmxlKGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkQm9vbExpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoODE4KTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhwYWNrZWRCb29sTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRCb29sXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUJvb2xOb1RhZyhwYWNrZWRCb29sXy5nZXRCb29sZWFuKGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRW51bUxpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoODI2KTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhwYWNrZWRFbnVtTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRFbnVtXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUVudW1Ob1RhZyhwYWNrZWRFbnVtXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZEludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKHBhY2tlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkSW50MzJMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkSW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRJbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQ2NFNpemVOb1RhZyhwYWNrZWRJbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRJbnQ2NExpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICBwYWNrZWRJbnQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUgPSBkYXRhU2l6ZTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZFVpbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVVSW50MzJTaXplTm9UYWcocGFja2VkVWludDMyXy5nZXRJbnQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkVWludDMyTGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZFVpbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSBkYXRhU2l6ZTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZFVpbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVVSW50NjRTaXplTm9UYWcocGFja2VkVWludDY0Xy5nZXRMb25nKGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZFVpbnQ2NExpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICBwYWNrZWRVaW50NjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRTaW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlU0ludDMyU2l6ZU5vVGFnKHBhY2tlZFNpbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZFNpbnQzMkxpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICBwYWNrZWRTaW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRTaW50NjRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlU0ludDY0U2l6ZU5vVGFnKHBhY2tlZFNpbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRTaW50NjRMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkU2ludDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gNCAqIGdldFBhY2tlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRGaXhlZDMyTGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZEZpeGVkMzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZGF0YVNpemUgPSA4ICogZ2V0UGFja2VkRml4ZWQ2NExpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZEZpeGVkNjRMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkRml4ZWQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUgPSBkYXRhU2l6ZTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDQgKiBnZXRQYWNrZWRTZml4ZWQzMkxpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZFNmaXhlZDMyTGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZFNmaXhlZDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gOCAqIGdldFBhY2tlZFNmaXhlZDY0TGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkU2ZpeGVkNjRMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkU2ZpeGVkNjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZGF0YVNpemUgPSA0ICogZ2V0UGFja2VkRmxvYXRMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRGbG9hdExpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICBwYWNrZWRGbG9hdE1lbW9pemVkU2VyaWFsaXplZFNpemUgPSBkYXRhU2l6ZTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDggKiBnZXRQYWNrZWREb3VibGVMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWREb3VibGVMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkRG91YmxlTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gMSAqIGdldFBhY2tlZEJvb2xMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRCb29sTGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZEJvb2xNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRFbnVtXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUVudW1TaXplTm9UYWcocGFja2VkRW51bV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZEVudW1MaXN0KCkuaXNFbXB0eSgpKSB7ICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVVSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH1wYWNrZWRFbnVtTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFnZXRQYWNrZWRJbnQzMkxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRQYWNrZWRJbnQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRQYWNrZWRJbnQ2NExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRQYWNrZWRJbnQ2NExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRQYWNrZWRVaW50MzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkVWludDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFBhY2tlZFVpbnQ2NExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRQYWNrZWRVaW50NjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkU2ludDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZFNpbnQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRQYWNrZWRTaW50NjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkU2ludDY0TGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFBhY2tlZEZpeGVkMzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkRml4ZWQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRQYWNrZWRGaXhlZDY0TGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZEZpeGVkNjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkU2ZpeGVkMzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkU2ZpeGVkMzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkU2ZpeGVkNjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkU2ZpeGVkNjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkRmxvYXRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkRmxvYXRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkRG91YmxlTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZERvdWJsZUxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRQYWNrZWRCb29sTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZEJvb2xMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghcGFja2VkRW51bV8uZXF1YWxzKG90aGVyLnBhY2tlZEVudW1fKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChnZXRQYWNrZWRJbnQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRJbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRJbnQ2NENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0lOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRJbnQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRVaW50MzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9VSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFBhY2tlZFVpbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRVaW50NjRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9VSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFBhY2tlZFVpbnQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRTaW50MzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9TSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFBhY2tlZFNpbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRTaW50NjRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9TSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFBhY2tlZFNpbnQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRGaXhlZDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfRklYRUQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGFja2VkRml4ZWQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRGaXhlZDY0Q291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfRklYRUQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGFja2VkRml4ZWQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRTZml4ZWQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX1NGSVhFRDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRTZml4ZWQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRTZml4ZWQ2NENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX1NGSVhFRDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRTZml4ZWQ2NExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRGbG9hdENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0ZMT0FUX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRGbG9hdExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWREb3VibGVDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9ET1VCTEVfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFBhY2tlZERvdWJsZUxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRCb29sQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfQk9PTF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGFja2VkQm9vbExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRFbnVtQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgcGFja2VkRW51bV8uaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkVHlwZXNMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRUeXBlc0xpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYWNrZWRUeXBlc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBwYWNrZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBwYWNrZWRJbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcGFja2VkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHBhY2tlZFVpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcGFja2VkU2ludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHBhY2tlZFNpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcGFja2VkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBwYWNrZWRGaXhlZDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICBwYWNrZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBwYWNrZWRTZml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcGFja2VkRmxvYXRfID0gZW1wdHlGbG9hdExpc3QoKTsKICAgICAgICBwYWNrZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgICAgcGFja2VkQm9vbF8gPSBlbXB0eUJvb2xlYW5MaXN0KCk7CiAgICAgICAgcGFja2VkRW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDIwMDApOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYWNrZWRUeXBlc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlKHRoaXMpOwogICAgICAgIGJ1aWxkUGFydGlhbFJlcGVhdGVkRmllbGRzKHJlc3VsdCk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbFJlcGVhdGVkRmllbGRzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcmVzdWx0KSB7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDIwMDApICE9IDApKSB7CiAgICAgICAgICBwYWNrZWRFbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHBhY2tlZEVudW1fKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnBhY2tlZEVudW1fID0gcGFja2VkRW51bV87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucGFja2VkSW50MzJfID0gcGFja2VkSW50MzJfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkSW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRJbnQ2NF8gPSBwYWNrZWRJbnQ2NF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgICBwYWNrZWRVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRVaW50MzJfID0gcGFja2VkVWludDMyXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZFVpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZFVpbnQ2NF8gPSBwYWNrZWRVaW50NjRfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkU2ludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucGFja2VkU2ludDMyXyA9IHBhY2tlZFNpbnQzMl87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgICBwYWNrZWRTaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRTaW50NjRfID0gcGFja2VkU2ludDY0XzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRGaXhlZDMyXyA9IHBhY2tlZEZpeGVkMzJfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDgwKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkRml4ZWQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZEZpeGVkNjRfID0gcGFja2VkRml4ZWQ2NF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAxMDApICE9IDApKSB7CiAgICAgICAgICBwYWNrZWRTZml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZFNmaXhlZDMyXyA9IHBhY2tlZFNmaXhlZDMyXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZFNmaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucGFja2VkU2ZpeGVkNjRfID0gcGFja2VkU2ZpeGVkNjRfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwNDAwKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkRmxvYXRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRGbG9hdF8gPSBwYWNrZWRGbG9hdF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgICBwYWNrZWREb3VibGVfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWREb3VibGVfID0gcGFja2VkRG91YmxlXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZEJvb2xfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRCb29sXyA9IHBhY2tlZEJvb2xfOwogICAgICAgIH0KICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAoIW90aGVyLnBhY2tlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChwYWNrZWRJbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZEludDMyXyA9IG90aGVyLnBhY2tlZEludDMyXzsKICAgICAgICAgICAgcGFja2VkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgcGFja2VkSW50MzJfLmFkZEFsbChvdGhlci5wYWNrZWRJbnQzMl8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkSW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZEludDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkSW50NjRfID0gb3RoZXIucGFja2VkSW50NjRfOwogICAgICAgICAgICBwYWNrZWRJbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRJbnQ2NF8uYWRkQWxsKG90aGVyLnBhY2tlZEludDY0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRVaW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZFVpbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZFVpbnQzMl8gPSBvdGhlci5wYWNrZWRVaW50MzJfOwogICAgICAgICAgICBwYWNrZWRVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZFVpbnQzMl8uYWRkQWxsKG90aGVyLnBhY2tlZFVpbnQzMl8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkVWludDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChwYWNrZWRVaW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWRVaW50NjRfID0gb3RoZXIucGFja2VkVWludDY0XzsKICAgICAgICAgICAgcGFja2VkVWludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZFVpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRVaW50NjRfLmFkZEFsbChvdGhlci5wYWNrZWRVaW50NjRfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnBhY2tlZFNpbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkU2ludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkU2ludDMyXyA9IG90aGVyLnBhY2tlZFNpbnQzMl87CiAgICAgICAgICAgIHBhY2tlZFNpbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRTaW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgcGFja2VkU2ludDMyXy5hZGRBbGwob3RoZXIucGFja2VkU2ludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRTaW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZFNpbnQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZFNpbnQ2NF8gPSBvdGhlci5wYWNrZWRTaW50NjRfOwogICAgICAgICAgICBwYWNrZWRTaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkU2ludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZFNpbnQ2NF8uYWRkQWxsKG90aGVyLnBhY2tlZFNpbnQ2NF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkRml4ZWQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkRml4ZWQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZEZpeGVkMzJfID0gb3RoZXIucGFja2VkRml4ZWQzMl87CiAgICAgICAgICAgIHBhY2tlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRGaXhlZDMyXy5hZGRBbGwob3RoZXIucGFja2VkRml4ZWQzMl8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkRml4ZWQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkRml4ZWQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZEZpeGVkNjRfID0gb3RoZXIucGFja2VkRml4ZWQ2NF87CiAgICAgICAgICAgIHBhY2tlZEZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRGaXhlZDY0Xy5hZGRBbGwob3RoZXIucGFja2VkRml4ZWQ2NF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkU2ZpeGVkMzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZFNmaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkU2ZpeGVkMzJfID0gb3RoZXIucGFja2VkU2ZpeGVkMzJfOwogICAgICAgICAgICBwYWNrZWRTZml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRTZml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRTZml4ZWQzMl8uYWRkQWxsKG90aGVyLnBhY2tlZFNmaXhlZDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRTZml4ZWQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkU2ZpeGVkNjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWRTZml4ZWQ2NF8gPSBvdGhlci5wYWNrZWRTZml4ZWQ2NF87CiAgICAgICAgICAgIHBhY2tlZFNmaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZFNmaXhlZDY0Xy5hZGRBbGwob3RoZXIucGFja2VkU2ZpeGVkNjRfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnBhY2tlZEZsb2F0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChwYWNrZWRGbG9hdF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZEZsb2F0XyA9IG90aGVyLnBhY2tlZEZsb2F0XzsKICAgICAgICAgICAgcGFja2VkRmxvYXRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkRmxvYXRJc011dGFibGUoKTsKICAgICAgICAgICAgcGFja2VkRmxvYXRfLmFkZEFsbChvdGhlci5wYWNrZWRGbG9hdF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkRG91YmxlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChwYWNrZWREb3VibGVfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWREb3VibGVfID0gb3RoZXIucGFja2VkRG91YmxlXzsKICAgICAgICAgICAgcGFja2VkRG91YmxlXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZERvdWJsZUlzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWREb3VibGVfLmFkZEFsbChvdGhlci5wYWNrZWREb3VibGVfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnBhY2tlZEJvb2xfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZEJvb2xfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWRCb29sXyA9IG90aGVyLnBhY2tlZEJvb2xfOwogICAgICAgICAgICBwYWNrZWRCb29sXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZEJvb2xJc011dGFibGUoKTsKICAgICAgICAgICAgcGFja2VkQm9vbF8uYWRkQWxsKG90aGVyLnBhY2tlZEJvb2xfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnBhY2tlZEVudW1fLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZEVudW1fLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWRFbnVtXyA9IG90aGVyLnBhY2tlZEVudW1fOwogICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMjAwMCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZEVudW1fLmFkZEFsbChvdGhlci5wYWNrZWRFbnVtXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA3MjA6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkSW50MzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3MjAKICAgICAgICAgICAgICBjYXNlIDcyMjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRJbnQzMl8uYWRkSW50KGlucHV0LnJlYWRJbnQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3MjIKICAgICAgICAgICAgICBjYXNlIDcyODogewogICAgICAgICAgICAgICAgbG9uZyB2ID0gaW5wdXQucmVhZEludDY0KCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkSW50NjRfLmFkZExvbmcodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzI4CiAgICAgICAgICAgICAgY2FzZSA3MzA6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkSW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkSW50NjRfLmFkZExvbmcoaW5wdXQucmVhZEludDY0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDczMAogICAgICAgICAgICAgIGNhc2UgNzM2OiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRVSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZFVpbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkVWludDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzM2CiAgICAgICAgICAgICAgY2FzZSA3Mzg6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHBhY2tlZFVpbnQzMl8uYWRkSW50KGlucHV0LnJlYWRVSW50MzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzM4CiAgICAgICAgICAgICAgY2FzZSA3NDQ6IHsKICAgICAgICAgICAgICAgIGxvbmcgdiA9IGlucHV0LnJlYWRVSW50NjQoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZFVpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkVWludDY0Xy5hZGRMb25nKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc0NAogICAgICAgICAgICAgIGNhc2UgNzQ2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZFVpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRVaW50NjRfLmFkZExvbmcoaW5wdXQucmVhZFVJbnQ2NCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3NDYKICAgICAgICAgICAgICBjYXNlIDc1MjogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkU0ludDMyKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRTaW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHBhY2tlZFNpbnQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc1MgogICAgICAgICAgICAgIGNhc2UgNzU0OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZFNpbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRTaW50MzJfLmFkZEludChpbnB1dC5yZWFkU0ludDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc1NAogICAgICAgICAgICAgIGNhc2UgNzYwOiB7CiAgICAgICAgICAgICAgICBsb25nIHYgPSBpbnB1dC5yZWFkU0ludDY0KCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHBhY2tlZFNpbnQ2NF8uYWRkTG9uZyh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3NjAKICAgICAgICAgICAgICBjYXNlIDc2MjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkU2ludDY0Xy5hZGRMb25nKGlucHV0LnJlYWRTSW50NjQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzYyCiAgICAgICAgICAgICAgY2FzZSA3NzM6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZEZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHBhY2tlZEZpeGVkMzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3NzMKICAgICAgICAgICAgICBjYXNlIDc3MDogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEZpeGVkMzJJc011dGFibGUoYWxsb2MgLyA0KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkRml4ZWQzMl8uYWRkSW50KGlucHV0LnJlYWRGaXhlZDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc3MAogICAgICAgICAgICAgIGNhc2UgNzc3OiB7CiAgICAgICAgICAgICAgICBsb25nIHYgPSBpbnB1dC5yZWFkRml4ZWQ2NCgpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkRml4ZWQ2NF8uYWRkTG9uZyh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3NzcKICAgICAgICAgICAgICBjYXNlIDc3ODogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEZpeGVkNjRJc011dGFibGUoYWxsb2MgLyA4KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkRml4ZWQ2NF8uYWRkTG9uZyhpbnB1dC5yZWFkRml4ZWQ2NCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3NzgKICAgICAgICAgICAgICBjYXNlIDc4OTogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkU0ZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZFNmaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRTZml4ZWQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc4OQogICAgICAgICAgICAgIGNhc2UgNzg2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkMzJJc011dGFibGUoYWxsb2MgLyA0KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkU2ZpeGVkMzJfLmFkZEludChpbnB1dC5yZWFkU0ZpeGVkMzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzg2CiAgICAgICAgICAgICAgY2FzZSA3OTM6IHsKICAgICAgICAgICAgICAgIGxvbmcgdiA9IGlucHV0LnJlYWRTRml4ZWQ2NCgpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHBhY2tlZFNmaXhlZDY0Xy5hZGRMb25nKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc5MwogICAgICAgICAgICAgIGNhc2UgNzk0OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkNjRJc011dGFibGUoYWxsb2MgLyA4KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkU2ZpeGVkNjRfLmFkZExvbmcoaW5wdXQucmVhZFNGaXhlZDY0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc5NAogICAgICAgICAgICAgIGNhc2UgODA1OiB7CiAgICAgICAgICAgICAgICBmbG9hdCB2ID0gaW5wdXQucmVhZEZsb2F0KCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRGbG9hdElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkRmxvYXRfLmFkZEZsb2F0KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgwNQogICAgICAgICAgICAgIGNhc2UgODAyOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkRmxvYXRJc011dGFibGUoYWxsb2MgLyA0KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkRmxvYXRfLmFkZEZsb2F0KGlucHV0LnJlYWRGbG9hdCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4MDIKICAgICAgICAgICAgICBjYXNlIDgwOTogewogICAgICAgICAgICAgICAgZG91YmxlIHYgPSBpbnB1dC5yZWFkRG91YmxlKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWREb3VibGVJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHBhY2tlZERvdWJsZV8uYWRkRG91YmxlKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgwOQogICAgICAgICAgICAgIGNhc2UgODEwOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkRG91YmxlSXNNdXRhYmxlKGFsbG9jIC8gOCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHBhY2tlZERvdWJsZV8uYWRkRG91YmxlKGlucHV0LnJlYWREb3VibGUoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODEwCiAgICAgICAgICAgICAgY2FzZSA4MTY6IHsKICAgICAgICAgICAgICAgIGJvb2xlYW4gdiA9IGlucHV0LnJlYWRCb29sKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRCb29sSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRCb29sXy5hZGRCb29sZWFuKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgxNgogICAgICAgICAgICAgIGNhc2UgODE4OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkQm9vbElzTXV0YWJsZShhbGxvYyAvIDEpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRCb29sXy5hZGRCb29sZWFuKGlucHV0LnJlYWRCb29sKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgxOAogICAgICAgICAgICAgIGNhc2UgODI0OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoMTAzLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkRW51bUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICBwYWNrZWRFbnVtXy5hZGQodG1wUmF3KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4MjQKICAgICAgICAgICAgICBjYXNlIDgyNjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IG9sZExpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICB3aGlsZShpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoMTAzLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgICBwYWNrZWRFbnVtXy5hZGQodG1wUmF3KTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQob2xkTGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgyNgogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCBwYWNrZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcGFja2VkSW50MzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRJbnQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkSW50MzJfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA5MCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRJbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFBhY2tlZEludDMyTGlzdCgpIHsKICAgICAgICBwYWNrZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRJbnQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBwYWNrZWRJbnQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA5MCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcGFja2VkSW50MzJfLmdldEludChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRJbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZEludDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkSW50MzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRJbnQzMl8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA5MCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkSW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkSW50MzJfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA5MCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBwYWNrZWRJbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZEludDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkSW50MzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcGFja2VkSW50MzJfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGFja2VkSW50MzIoKSB7CiAgICAgICAgcGFja2VkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcGFja2VkSW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkSW50NjRJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWRJbnQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZEludDY0XyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRJbnQ2NF8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEludDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0UGFja2VkSW50NjRMaXN0KCkgewogICAgICAgIHBhY2tlZEludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHBhY2tlZEludDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkSW50NjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZEludDY0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEludDY0Xy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRJbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgbG9uZyBnZXRQYWNrZWRJbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcGFja2VkSW50NjRfLmdldExvbmcoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCBwYWNrZWRfaW50NjQgPSA5MSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkSW50NjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWRJbnQ2NCgKICAgICAgICAgIGludCBpbmRleCwgbG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEludDY0Xy5zZXRMb25nKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCBwYWNrZWRfaW50NjQgPSA5MSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEludDY0IHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkSW50NjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEludDY0Xy5hZGRMb25nKHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZEludDY0IHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkSW50NjQoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRJbnQ2NF8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRJbnQ2NCgpIHsKICAgICAgICBwYWNrZWRJbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCBwYWNrZWRVaW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRVaW50MzJJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWRVaW50MzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRVaW50MzJfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZFVpbnQzMl8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkVWludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UGFja2VkVWludDMyTGlzdCgpIHsKICAgICAgICBwYWNrZWRVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcGFja2VkVWludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHBhY2tlZF91aW50MzIgPSA5MiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRVaW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZFVpbnQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBwYWNrZWRVaW50MzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHBhY2tlZF91aW50MzIgPSA5MiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkVWludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkVWludDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRVaW50MzJfLmdldEludChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZFVpbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZFVpbnQzMigKICAgICAgICAgIGludCBpbmRleCwgaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZFVpbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZFVpbnQzMl8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkVWludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkVWludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRVaW50MzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRVaW50MzJfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZFVpbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZFVpbnQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVBhY2tlZFVpbnQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRVaW50MzJfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRVaW50MzIoKSB7CiAgICAgICAgcGFja2VkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHBhY2tlZFVpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRVaW50NjRJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWRVaW50NjRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRVaW50NjRfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZFVpbnQ2NF8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCBwYWNrZWRfdWludDY0ID0gOTMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkVWludDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0UGFja2VkVWludDY0TGlzdCgpIHsKICAgICAgICBwYWNrZWRVaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcGFja2VkVWludDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRVaW50NjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZFVpbnQ2NENvdW50KCkgewogICAgICAgIHJldHVybiBwYWNrZWRVaW50NjRfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkVWludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBsb25nIGdldFBhY2tlZFVpbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcGFja2VkVWludDY0Xy5nZXRMb25nKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkVWludDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkVWludDY0KAogICAgICAgICAgaW50IGluZGV4LCBsb25nIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZFVpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZFVpbnQ2NF8uc2V0TG9uZyhpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZFVpbnQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZFVpbnQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZFVpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZFVpbnQ2NF8uYWRkTG9uZyh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZFVpbnQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZFVpbnQ2NCgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkxvbmc+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVBhY2tlZFVpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRVaW50NjRfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCBwYWNrZWRfdWludDY0ID0gOTMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRVaW50NjQoKSB7CiAgICAgICAgcGFja2VkVWludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwOCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZFNpbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZFNpbnQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZFNpbnQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZFNpbnQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkU2ludDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHBhY2tlZF9zaW50MzIgPSA5NCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTaW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRQYWNrZWRTaW50MzJMaXN0KCkgewogICAgICAgIHBhY2tlZFNpbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRTaW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNpbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkU2ludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNpbnQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRTaW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRTaW50MzIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNpbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHBhY2tlZF9zaW50MzIgPSA5NCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkU2ludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkU2ludDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkU2ludDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiBwYWNrZWRfc2ludDMyID0gOTQgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRTaW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRTaW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZFNpbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZFNpbnQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiBwYWNrZWRfc2ludDMyID0gOTQgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkU2ludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkU2ludDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZFNpbnQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHBhY2tlZF9zaW50MzIgPSA5NCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZFNpbnQzMigpIHsKICAgICAgICBwYWNrZWRTaW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcGFja2VkU2ludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZFNpbnQ2NElzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZFNpbnQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZFNpbnQ2NF8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkU2ludDY0Xyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHBhY2tlZF9zaW50NjQgPSA5NSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTaW50NjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRQYWNrZWRTaW50NjRMaXN0KCkgewogICAgICAgIHBhY2tlZFNpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRTaW50NjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNpbnQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkU2ludDY0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNpbnQ2NF8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRTaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGxvbmcgZ2V0UGFja2VkU2ludDY0KGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRTaW50NjRfLmdldExvbmcoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRTaW50NjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWRTaW50NjQoCiAgICAgICAgICBpbnQgaW5kZXgsIGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkU2ludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkU2ludDY0Xy5zZXRMb25nKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkU2ludDY0IHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkU2ludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkU2ludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkU2ludDY0Xy5hZGRMb25nKHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCBwYWNrZWRfc2ludDY0ID0gOTUgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkU2ludDY0IHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkU2ludDY0KAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkU2ludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZFNpbnQ2NF8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHBhY2tlZF9zaW50NjQgPSA5NSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZFNpbnQ2NCgpIHsKICAgICAgICBwYWNrZWRTaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDIwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZEZpeGVkMzJJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWRGaXhlZDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkRml4ZWQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkRml4ZWQzMl8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZEZpeGVkMzJJc011dGFibGUoaW50IGNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFwYWNrZWRGaXhlZDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkRml4ZWQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkRml4ZWQzMl8sIGNhcGFjaXR5KTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkRml4ZWQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFBhY2tlZEZpeGVkMzJMaXN0KCkgewogICAgICAgIHBhY2tlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcGFja2VkRml4ZWQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcGFja2VkX2ZpeGVkMzIgPSA5NiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRGaXhlZDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRGaXhlZDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEZpeGVkMzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRGaXhlZDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkRml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcGFja2VkRml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRGaXhlZDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkRml4ZWQzMigKICAgICAgICAgIGludCBpbmRleCwgaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRGaXhlZDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcGFja2VkX2ZpeGVkMzIgPSA5NiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEZpeGVkMzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRGaXhlZDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkRml4ZWQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcGFja2VkX2ZpeGVkMzIgPSA5NiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBwYWNrZWRGaXhlZDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkRml4ZWQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVBhY2tlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcGFja2VkRml4ZWQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGFja2VkRml4ZWQzMigpIHsKICAgICAgICBwYWNrZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDQwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHBhY2tlZEZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkRml4ZWQ2NElzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZEZpeGVkNjRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRGaXhlZDY0XyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRGaXhlZDY0Xyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkRml4ZWQ2NElzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXBhY2tlZEZpeGVkNjRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRGaXhlZDY0XyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRGaXhlZDY0XywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRGaXhlZDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0UGFja2VkRml4ZWQ2NExpc3QoKSB7CiAgICAgICAgcGFja2VkRml4ZWQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRGaXhlZDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEZpeGVkNjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZEZpeGVkNjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkRml4ZWQ2NF8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHBhY2tlZF9maXhlZDY0ID0gOTcgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEZpeGVkNjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGxvbmcgZ2V0UGFja2VkRml4ZWQ2NChpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcGFja2VkRml4ZWQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkRml4ZWQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZEZpeGVkNjQoCiAgICAgICAgICBpbnQgaW5kZXgsIGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEZpeGVkNjRfLnNldExvbmcoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEZpeGVkNjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRGaXhlZDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEZpeGVkNjRfLmFkZExvbmcodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZEZpeGVkNjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRGaXhlZDY0KAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRGaXhlZDY0Xyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHBhY2tlZF9maXhlZDY0ID0gOTcgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRGaXhlZDY0KCkgewogICAgICAgIHBhY2tlZEZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDgwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkU2ZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRTZml4ZWQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZFNmaXhlZDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkU2ZpeGVkMzJfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZFNmaXhlZDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkU2ZpeGVkMzJJc011dGFibGUoaW50IGNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFwYWNrZWRTZml4ZWQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZFNmaXhlZDMyXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRTZml4ZWQzMl8sIGNhcGFjaXR5KTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiBwYWNrZWRfc2ZpeGVkMzIgPSA5OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTZml4ZWQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFBhY2tlZFNmaXhlZDMyTGlzdCgpIHsKICAgICAgICBwYWNrZWRTZml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNmaXhlZDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRTZml4ZWQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiBwYWNrZWRfc2ZpeGVkMzIgPSA5OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkU2ZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRTZml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcGFja2VkU2ZpeGVkMzJfLmdldEludChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRTZml4ZWQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZFNmaXhlZDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRTZml4ZWQzMl8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiBwYWNrZWRfc2ZpeGVkMzIgPSA5OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZFNmaXhlZDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkU2ZpeGVkMzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZFNmaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkU2ZpeGVkMzJfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiBwYWNrZWRfc2ZpeGVkMzIgPSA5OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBwYWNrZWRTZml4ZWQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZFNmaXhlZDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcGFja2VkU2ZpeGVkMzJfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGFja2VkU2ZpeGVkMzIoKSB7CiAgICAgICAgcGFja2VkU2ZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAxMDApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcGFja2VkU2ZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkU2ZpeGVkNjRJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWRTZml4ZWQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZFNmaXhlZDY0XyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRTZml4ZWQ2NF8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZFNmaXhlZDY0SXNNdXRhYmxlKGludCBjYXBhY2l0eSkgewogICAgICAgIGlmICghcGFja2VkU2ZpeGVkNjRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRTZml4ZWQ2NF8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkU2ZpeGVkNjRfLCBjYXBhY2l0eSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkU2ZpeGVkNjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRQYWNrZWRTZml4ZWQ2NExpc3QoKSB7CiAgICAgICAgcGFja2VkU2ZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcGFja2VkU2ZpeGVkNjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCBwYWNrZWRfc2ZpeGVkNjQgPSA5OSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRTZml4ZWQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkU2ZpeGVkNjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkU2ZpeGVkNjRfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFNmaXhlZDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBsb25nIGdldFBhY2tlZFNmaXhlZDY0KGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRTZml4ZWQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZFNmaXhlZDY0KAogICAgICAgICAgaW50IGluZGV4LCBsb25nIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkU2ZpeGVkNjRfLnNldExvbmcoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkU2ZpeGVkNjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRTZml4ZWQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkU2ZpeGVkNjRfLmFkZExvbmcodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkU2ZpeGVkNjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRTZml4ZWQ2NCgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkxvbmc+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVBhY2tlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZFNmaXhlZDY0Xyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCBwYWNrZWRfc2ZpeGVkNjQgPSA5OSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZFNmaXhlZDY0KCkgewogICAgICAgIHBhY2tlZFNmaXhlZDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDIwMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5GbG9hdExpc3QgcGFja2VkRmxvYXRfID0gZW1wdHlGbG9hdExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZEZsb2F0SXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcGFja2VkRmxvYXRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRGbG9hdF8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkRmxvYXRfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRGbG9hdElzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXBhY2tlZEZsb2F0Xy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkRmxvYXRfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZEZsb2F0XywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHBhY2tlZF9mbG9hdCA9IDEwMCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRGbG9hdC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgICBnZXRQYWNrZWRGbG9hdExpc3QoKSB7CiAgICAgICAgcGFja2VkRmxvYXRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcGFja2VkRmxvYXRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkRmxvYXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZEZsb2F0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEZsb2F0Xy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHBhY2tlZF9mbG9hdCA9IDEwMCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkRmxvYXQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGZsb2F0IGdldFBhY2tlZEZsb2F0KGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRGbG9hdF8uZ2V0RmxvYXQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEZsb2F0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkRmxvYXQoCiAgICAgICAgICBpbnQgaW5kZXgsIGZsb2F0IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEZsb2F0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkRmxvYXRfLnNldEZsb2F0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRGbG9hdCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZEZsb2F0KGZsb2F0IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEZsb2F0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkRmxvYXRfLmFkZEZsb2F0KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHBhY2tlZF9mbG9hdCA9IDEwMCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBwYWNrZWRGbG9hdCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZEZsb2F0KAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuRmxvYXQ+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVBhY2tlZEZsb2F0SXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZEZsb2F0Xyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRGbG9hdCgpIHsKICAgICAgICBwYWNrZWRGbG9hdF8gPSBlbXB0eUZsb2F0TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwNDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkRvdWJsZUxpc3QgcGFja2VkRG91YmxlXyA9IGVtcHR5RG91YmxlTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkRG91YmxlSXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcGFja2VkRG91YmxlXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkRG91YmxlXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWREb3VibGVfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWREb3VibGVJc011dGFibGUoaW50IGNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFwYWNrZWREb3VibGVfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWREb3VibGVfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZERvdWJsZV8sIGNhcGFjaXR5KTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcGFja2VkX2RvdWJsZSA9IDEwMSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWREb3VibGUuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkRvdWJsZT4KICAgICAgICAgIGdldFBhY2tlZERvdWJsZUxpc3QoKSB7CiAgICAgICAgcGFja2VkRG91YmxlXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHBhY2tlZERvdWJsZV87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSBwYWNrZWRfZG91YmxlID0gMTAxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZERvdWJsZS4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkRG91YmxlQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZERvdWJsZV8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcGFja2VkX2RvdWJsZSA9IDEwMSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkRG91YmxlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBkb3VibGUgZ2V0UGFja2VkRG91YmxlKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWREb3VibGVfLmdldERvdWJsZShpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSBwYWNrZWRfZG91YmxlID0gMTAxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWREb3VibGUgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWREb3VibGUoCiAgICAgICAgICBpbnQgaW5kZXgsIGRvdWJsZSB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWREb3VibGVJc011dGFibGUoKTsKICAgICAgICBwYWNrZWREb3VibGVfLnNldERvdWJsZShpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWREb3VibGUgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWREb3VibGUoZG91YmxlIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZERvdWJsZUlzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZERvdWJsZV8uYWRkRG91YmxlKHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSBwYWNrZWRfZG91YmxlID0gMTAxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZERvdWJsZSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZERvdWJsZSgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkRvdWJsZT4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkRG91YmxlSXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZERvdWJsZV8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWREb3VibGUoKSB7CiAgICAgICAgcGFja2VkRG91YmxlXyA9IGVtcHR5RG91YmxlTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwODAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkJvb2xlYW5MaXN0IHBhY2tlZEJvb2xfID0gZW1wdHlCb29sZWFuTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkQm9vbElzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZEJvb2xfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRCb29sXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRCb29sXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkQm9vbElzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXBhY2tlZEJvb2xfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRCb29sXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRCb29sXywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkQm9vbC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuQm9vbGVhbj4KICAgICAgICAgIGdldFBhY2tlZEJvb2xMaXN0KCkgewogICAgICAgIHBhY2tlZEJvb2xfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcGFja2VkQm9vbF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkQm9vbC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkQm9vbENvdW50KCkgewogICAgICAgIHJldHVybiBwYWNrZWRCb29sXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEJvb2wgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gZ2V0UGFja2VkQm9vbChpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcGFja2VkQm9vbF8uZ2V0Qm9vbGVhbihpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEJvb2wgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWRCb29sKAogICAgICAgICAgaW50IGluZGV4LCBib29sZWFuIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEJvb2xJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRCb29sXy5zZXRCb29sZWFuKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHBhY2tlZF9ib29sID0gMTAyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkQm9vbCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZEJvb2woYm9vbGVhbiB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRCb29sSXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkQm9vbF8uYWRkQm9vbGVhbih2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHBhY2tlZF9ib29sID0gMTAyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZEJvb2wgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRCb29sKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuQm9vbGVhbj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkQm9vbElzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRCb29sXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHBhY2tlZF9ib29sID0gMTAyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGFja2VkQm9vbCgpIHsKICAgICAgICBwYWNrZWRCb29sXyA9IGVtcHR5Qm9vbGVhbkxpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMTAwMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IHBhY2tlZEVudW1fID0KICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRFbnVtSXNNdXRhYmxlKCkgewogICAgICAgIGlmICghKChiaXRGaWVsZDBfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZEVudW1fID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8amF2YS5sYW5nLkludGVnZXI+KHBhY2tlZEVudW1fKTsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHBhY2tlZF9lbnVtID0gMTAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEVudW0uCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPiBnZXRQYWNrZWRFbnVtTGlzdCgpIHsKICAgICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXI8CiAgICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+KHBhY2tlZEVudW1fLCBwYWNrZWRFbnVtX2NvbnZlcnRlcl8pOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRFbnVtLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRFbnVtQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEVudW1fLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEVudW0gYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRQYWNrZWRFbnVtKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRFbnVtX2NvbnZlcnRlcl8uY29udmVydChwYWNrZWRFbnVtXy5nZXQoaW5kZXgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWRFbnVtKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGVuc3VyZVBhY2tlZEVudW1Jc011dGFibGUoKTsKICAgICAgICBwYWNrZWRFbnVtXy5zZXQoaW5kZXgsIHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRFbnVtIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkRW51bShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGVuc3VyZVBhY2tlZEVudW1Jc011dGFibGUoKTsKICAgICAgICBwYWNrZWRFbnVtXy5hZGQodmFsdWUuZ2V0TnVtYmVyKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBwYWNrZWRFbnVtIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkRW51bSgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgZm9yIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdmFsdWUgOiB2YWx1ZXMpIHsKICAgICAgICAgIHBhY2tlZEVudW1fLmFkZCh2YWx1ZS5nZXROdW1iZXIoKSk7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZEVudW0oKSB7CiAgICAgICAgcGFja2VkRW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDIwMDApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkVHlwZXNMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZFR5cGVzTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RQYWNrZWRUeXBlc0xpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdFBhY2tlZFR5cGVzTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RQYWNrZWRUeXBlc0xpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0UGFja2VkVHlwZXNMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RQYWNrZWRUeXBlc0xpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0QWxsRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuCiAgICAgICAgICBFeHRlbmRhYmxlTWVzc2FnZU9yQnVpbGRlcjxUZXN0QWxsRXh0ZW5zaW9uc0xpdGU+IHsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RBbGxFeHRlbnNpb25zTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVNZXNzYWdlPAogICAgICAgIFRlc3RBbGxFeHRlbnNpb25zTGl0ZT4gaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpCiAgICAgIFRlc3RBbGxFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdEFsbEV4dGVuc2lvbnNMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RBbGxFeHRlbnNpb25zTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlQnVpbGRlcjxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsID8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RBbGxFeHRlbnNpb25zTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0QWxsRXh0ZW5zaW9uc0xpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuRXh0ZW5kYWJsZU1lc3NhZ2U8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlPi5FeHRlbnNpb25Xcml0ZXIKICAgICAgICAgIGV4dGVuc2lvbldyaXRlciA9IG5ld0V4dGVuc2lvbldyaXRlcigpOwogICAgICBleHRlbnNpb25Xcml0ZXIud3JpdGVVbnRpbCg1MzY4NzA5MTIsIG91dHB1dCk7CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBzaXplICs9IGV4dGVuc2lvbnNTZXJpYWxpemVkU2l6ZSgpOwogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpIG9iajsKCiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0RXh0ZW5zaW9uRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldEV4dGVuc2lvbkZpZWxkcygpKSkKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaGFzaCA9IGhhc2hGaWVsZHMoaGFzaCwgZ2V0RXh0ZW5zaW9uRmllbGRzKCkpOwogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlQnVpbGRlcjwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwgQnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSh0aGlzKTsKICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIHNldEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLCBUeXBlPiBleHRlbnNpb24sCiAgICAgICAgICBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIGludCBpbmRleCwgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRFeHRlbnNpb24oZXh0ZW5zaW9uLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIGFkZEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRFeHRlbnNpb24oZXh0ZW5zaW9uLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFQ+IEJ1aWxkZXIgY2xlYXJFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwgVD4gZXh0ZW5zaW9uKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRXh0ZW5zaW9uKGV4dGVuc2lvbik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgdGhpcy5tZXJnZUV4dGVuc2lvbkZpZWxkcyhvdGhlcik7CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGlmICghZXh0ZW5zaW9uc0FyZUluaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEFsbEV4dGVuc2lvbnNMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RBbGxFeHRlbnNpb25zTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RBbGxFeHRlbnNpb25zTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0QWxsRXh0ZW5zaW9uc0xpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIE9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0Lk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNBKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBpbnQgZ2V0QSgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIE9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0Lk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICAgIE9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIE9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIE9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEFfRklFTERfTlVNQkVSID0gMTc7CiAgICBwcml2YXRlIGludCBhXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgIHJldHVybiBhXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDE3LCBhXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMTcsIGFfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpIG9iajsKCiAgICAgIGlmIChoYXNBKCkgIT0gb3RoZXIuaGFzQSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICBpZiAoZ2V0QSgpCiAgICAgICAgICAgICE9IG90aGVyLmdldEEoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0EoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEFfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEEoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0Lk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X09wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBhXyA9IDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5hXyA9IGFfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNBKCkpIHsKICAgICAgICAgIHNldEEob3RoZXIuZ2V0QSgpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAxMzY6IHsKICAgICAgICAgICAgICAgIGFfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTM2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IGFfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0EoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgICAgcmV0dXJuIGFfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGEgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRBKGludCB2YWx1ZSkgewoKICAgICAgICBhXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJBKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBhXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0Lk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxPcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNBKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBpbnQgZ2V0QSgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICAgIFJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEFfRklFTERfTlVNQkVSID0gNDc7CiAgICBwcml2YXRlIGludCBhXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgIHJldHVybiBhXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDQ3LCBhXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoNDcsIGFfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpIG9iajsKCiAgICAgIGlmIChoYXNBKCkgIT0gb3RoZXIuaGFzQSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICBpZiAoZ2V0QSgpCiAgICAgICAgICAgICE9IG90aGVyLmdldEEoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0EoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEFfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEEoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBhXyA9IDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5hXyA9IGFfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNBKCkpIHsKICAgICAgICAgIHNldEEob3RoZXIuZ2V0QSgpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAzNzY6IHsKICAgICAgICAgICAgICAgIGFfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzc2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IGFfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0EoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgICAgcmV0dXJuIGFfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGEgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRBKGludCB2YWx1ZSkgewoKICAgICAgICBhXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJBKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBhXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxSZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy4KICAgICAgICAgIEV4dGVuZGFibGVNZXNzYWdlT3JCdWlsZGVyPFRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZT4gewogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZU1lc3NhZ2U8CiAgICAgICAgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlPiBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSkKICAgICAgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwgPz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBpZiAoIWV4dGVuc2lvbnNBcmVJbml0aWFsaXplZCgpKSB7CiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5FeHRlbmRhYmxlTWVzc2FnZTxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGU+LkV4dGVuc2lvbldyaXRlcgogICAgICAgICAgZXh0ZW5zaW9uV3JpdGVyID0gbmV3RXh0ZW5zaW9uV3JpdGVyKCk7CiAgICAgIGV4dGVuc2lvbldyaXRlci53cml0ZVVudGlsKDUzNjg3MDkxMiwgb3V0cHV0KTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHNpemUgKz0gZXh0ZW5zaW9uc1NlcmlhbGl6ZWRTaXplKCk7CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRFeHRlbnNpb25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0RXh0ZW5zaW9uRmllbGRzKCkpKQogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBoYXNoID0gaGFzaEZpZWxkcyhoYXNoLCBnZXRFeHRlbnNpb25GaWVsZHMoKSk7CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLCBCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKHRoaXMpOwogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgc2V0RXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsIFR5cGU+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIHNldEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgaW50IGluZGV4LCBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgYWRkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsIGphdmEudXRpbC5MaXN0PFR5cGU+PiBleHRlbnNpb24sCiAgICAgICAgICBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZEV4dGVuc2lvbihleHRlbnNpb24sIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VD4gQnVpbGRlciBjbGVhckV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLCBUPiBleHRlbnNpb24pIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJFeHRlbnNpb24oZXh0ZW5zaW9uKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICB0aGlzLm1lcmdlRXh0ZW5zaW9uRmllbGRzKG90aGVyKTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUpCiAgICAgIFRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKSBvYmo7CgogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3ROZXN0ZWRFeHRlbnNpb25MaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3ROZXN0ZWRFeHRlbnNpb25MaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUodGhpcyk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE5lc3RlZEV4dGVuc2lvbkxpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdE5lc3RlZEV4dGVuc2lvbkxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBORVNURURfRVhURU5TSU9OX0ZJRUxEX05VTUJFUiA9IDEyMzQ1OwogICAgLyoqCiAgICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gbmVzdGVkRXh0ZW5zaW9uID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAgIC5uZXdNZXNzYWdlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCksCiAgICAgICAgICAwLAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgICBudWxsKTsKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdERlcHJlY2F0ZWRMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZCBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NAogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVwcmVjYXRlZF9maWVsZCA9IDEgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDQKICAgICAqIEByZXR1cm4gVGhlIGRlcHJlY2F0ZWRGaWVsZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGludCBnZXREZXByZWNhdGVkRmllbGQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGRlcHJlY2F0ZWRfZmllbGQyID0gMiBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDIgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDUKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDIoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgZGVwcmVjYXRlZF9maWVsZDIgPSAyIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkMiBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NQogICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkMi4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGludCBnZXREZXByZWNhdGVkRmllbGQyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkMyBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGJvb2xlYW4gaGFzRGVwcmVjYXRlZEZpZWxkMygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkMyBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NgogICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkMy4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVwcmVjYXRlZEZpZWxkMygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkMyBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlcHJlY2F0ZWRGaWVsZDMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZXByZWNhdGVkRmllbGQzQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDQgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDcKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkNCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZF9maWVsZDQgPSA0IFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkNCBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NwogICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkNC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBnZXREZXByZWNhdGVkRmllbGQ0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZU9yQnVpbGRlciBnZXREZXByZWNhdGVkRmllbGQ0T3JCdWlsZGVyKCk7CiAgfQogIC8qKgogICAqIDxwcmU+CiAgICogVGVzdCB0aGF0IGRlcHJlY2F0ZWQgZmllbGRzIHdvcmsuICBXZSBvbmx5IHZlcmlmeSB0aGF0IHRoZXkgY29tcGlsZSAoYXQgb25lCiAgICogcG9pbnQgdGhpcyBmYWlsZWQpLgogICAqIDwvcHJlPgogICAqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3REZXByZWNhdGVkTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlKQogICAgICBUZXN0RGVwcmVjYXRlZExpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3REZXByZWNhdGVkTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0RGVwcmVjYXRlZExpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0RGVwcmVjYXRlZExpdGUoKSB7CiAgICAgIGRlcHJlY2F0ZWRGaWVsZDNfID0gIiI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdERlcHJlY2F0ZWRMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3REZXByZWNhdGVkTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERVBSRUNBVEVEX0ZJRUxEX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIGludCBkZXByZWNhdGVkRmllbGRfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVwcmVjYXRlZF9maWVsZCA9IDEgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDQKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZCBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NAogICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGludCBnZXREZXByZWNhdGVkRmllbGQoKSB7CiAgICAgIHJldHVybiBkZXByZWNhdGVkRmllbGRfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFUFJFQ0FURURfRklFTEQyX0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIGludCBkZXByZWNhdGVkRmllbGQyXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGRlcHJlY2F0ZWRfZmllbGQyID0gMiBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDIgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDUKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQyKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGRlcHJlY2F0ZWRfZmllbGQyID0gMiBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDIgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDUKICAgICAqIEByZXR1cm4gVGhlIGRlcHJlY2F0ZWRGaWVsZDIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgaW50IGdldERlcHJlY2F0ZWRGaWVsZDIoKSB7CiAgICAgIHJldHVybiBkZXByZWNhdGVkRmllbGQyXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERVBSRUNBVEVEX0ZJRUxEM19GSUVMRF9OVU1CRVIgPSAzOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIHZvbGF0aWxlIGphdmEubGFuZy5PYmplY3QgZGVwcmVjYXRlZEZpZWxkM18gPSAiIjsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlcHJlY2F0ZWRfZmllbGQzID0gMyBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDMgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDYKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkMyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQzKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZXByZWNhdGVkX2ZpZWxkMyA9IDMgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQzIGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ2CiAgICAgKiBAcmV0dXJuIFRoZSBkZXByZWNhdGVkRmllbGQzLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVwcmVjYXRlZEZpZWxkMygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZXByZWNhdGVkRmllbGQzXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZXByZWNhdGVkX2ZpZWxkMyA9IDMgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQzIGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ2CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVwcmVjYXRlZEZpZWxkMy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZXByZWNhdGVkRmllbGQzQnl0ZXMoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVwcmVjYXRlZEZpZWxkM187CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIGRlcHJlY2F0ZWRGaWVsZDNfID0gYjsKICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVQUkVDQVRFRF9GSUVMRDRfRklFTERfTlVNQkVSID0gNDsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRGaWVsZDRfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQ0IGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ3CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlcHJlY2F0ZWRGaWVsZDQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGJvb2xlYW4gaGFzRGVwcmVjYXRlZEZpZWxkNCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQ0IGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ3CiAgICAgKiBAcmV0dXJuIFRoZSBkZXByZWNhdGVkRmllbGQ0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBnZXREZXByZWNhdGVkRmllbGQ0KCkgewogICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkNF8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGRlcHJlY2F0ZWRGaWVsZDRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlT3JCdWlsZGVyIGdldERlcHJlY2F0ZWRGaWVsZDRPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBkZXByZWNhdGVkRmllbGQ0XyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogZGVwcmVjYXRlZEZpZWxkNF87CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgaWYgKCFoYXNEZXByZWNhdGVkRmllbGQyKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVwcmVjYXRlZEZpZWxkNCgpKSB7CiAgICAgICAgaWYgKCFnZXREZXByZWNhdGVkRmllbGQ0KCkuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGRlcHJlY2F0ZWRGaWVsZF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDIsIGRlcHJlY2F0ZWRGaWVsZDJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDMsIGRlcHJlY2F0ZWRGaWVsZDNfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDQsIGdldERlcHJlY2F0ZWRGaWVsZDQoKSk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMSwgZGVwcmVjYXRlZEZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgyLCBkZXByZWNhdGVkRmllbGQyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5jb21wdXRlU3RyaW5nU2l6ZSgzLCBkZXByZWNhdGVkRmllbGQzXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDQsIGdldERlcHJlY2F0ZWRGaWVsZDQoKSk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlKSBvYmo7CgogICAgICBpZiAoaGFzRGVwcmVjYXRlZEZpZWxkKCkgIT0gb3RoZXIuaGFzRGVwcmVjYXRlZEZpZWxkKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZCgpKSB7CiAgICAgICAgaWYgKGdldERlcHJlY2F0ZWRGaWVsZCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlcHJlY2F0ZWRGaWVsZCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDIoKSAhPSBvdGhlci5oYXNEZXByZWNhdGVkRmllbGQyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDIoKSkgewogICAgICAgIGlmIChnZXREZXByZWNhdGVkRmllbGQyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVwcmVjYXRlZEZpZWxkMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDMoKSAhPSBvdGhlci5oYXNEZXByZWNhdGVkRmllbGQzKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDMoKSkgewogICAgICAgIGlmICghZ2V0RGVwcmVjYXRlZEZpZWxkMygpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RGVwcmVjYXRlZEZpZWxkMygpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQ0KCkgIT0gb3RoZXIuaGFzRGVwcmVjYXRlZEZpZWxkNCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQ0KCkpIHsKICAgICAgICBpZiAoIWdldERlcHJlY2F0ZWRGaWVsZDQoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldERlcHJlY2F0ZWRGaWVsZDQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFUFJFQ0FURURfRklFTERfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlcHJlY2F0ZWRGaWVsZCgpOwogICAgICB9CiAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERVBSRUNBVEVEX0ZJRUxEMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RGVwcmVjYXRlZEZpZWxkMigpOwogICAgICB9CiAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQzKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERVBSRUNBVEVEX0ZJRUxEM19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RGVwcmVjYXRlZEZpZWxkMygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFUFJFQ0FURURfRklFTEQ0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZXByZWNhdGVkRmllbGQ0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRlc3QgdGhhdCBkZXByZWNhdGVkIGZpZWxkcyB3b3JrLiAgV2Ugb25seSB2ZXJpZnkgdGhhdCB0aGV5IGNvbXBpbGUgKGF0IG9uZQogICAgICogcG9pbnQgdGhpcyBmYWlsZWQpLgogICAgICogPC9wcmU+CiAgICAgKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdERlcHJlY2F0ZWRMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdERlcHJlY2F0ZWRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCkgewogICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMpIHsKICAgICAgICAgIGdldERlcHJlY2F0ZWRGaWVsZDRGaWVsZEJ1aWxkZXIoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGRlcHJlY2F0ZWRGaWVsZF8gPSAwOwogICAgICAgIGRlcHJlY2F0ZWRGaWVsZDJfID0gMDsKICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9ICIiOwogICAgICAgIGRlcHJlY2F0ZWRGaWVsZDRfID0gbnVsbDsKICAgICAgICBpZiAoZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlcHJlY2F0ZWRGaWVsZF8gPSBkZXByZWNhdGVkRmllbGRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlcHJlY2F0ZWRGaWVsZDJfID0gZGVwcmVjYXRlZEZpZWxkMl87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVwcmVjYXRlZEZpZWxkM18gPSBkZXByZWNhdGVkRmllbGQzXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZXByZWNhdGVkRmllbGQ0XyA9IGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgPyBkZXByZWNhdGVkRmllbGQ0XwogICAgICAgICAgICAgIDogZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzRGVwcmVjYXRlZEZpZWxkKCkpIHsKICAgICAgICAgIHNldERlcHJlY2F0ZWRGaWVsZChvdGhlci5nZXREZXByZWNhdGVkRmllbGQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZXByZWNhdGVkRmllbGQyKCkpIHsKICAgICAgICAgIHNldERlcHJlY2F0ZWRGaWVsZDIob3RoZXIuZ2V0RGVwcmVjYXRlZEZpZWxkMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlcHJlY2F0ZWRGaWVsZDMoKSkgewogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkM18gPSBvdGhlci5kZXByZWNhdGVkRmllbGQzXzsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVwcmVjYXRlZEZpZWxkNCgpKSB7CiAgICAgICAgICBtZXJnZURlcHJlY2F0ZWRGaWVsZDQob3RoZXIuZ2V0RGVwcmVjYXRlZEZpZWxkNCgpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGlmICghaGFzRGVwcmVjYXRlZEZpZWxkMigpKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQ0KCkpIHsKICAgICAgICAgIGlmICghZ2V0RGVwcmVjYXRlZEZpZWxkNCgpLmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICBkZXByZWNhdGVkRmllbGRfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGNhc2UgMTY6IHsKICAgICAgICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDJfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYKICAgICAgICAgICAgICBjYXNlIDI2OiB7CiAgICAgICAgICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI2CiAgICAgICAgICAgICAgY2FzZSAzNDogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0RGVwcmVjYXRlZEZpZWxkNEZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzQKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBpbnQgZGVwcmVjYXRlZEZpZWxkXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQGRlcHJlY2F0ZWQgcHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkIGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDQKICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGJvb2xlYW4gaGFzRGVwcmVjYXRlZEZpZWxkKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVwcmVjYXRlZF9maWVsZCA9IDEgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZCBpcyBkZXByZWNhdGVkLgogICAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ0CiAgICAgICAqIEByZXR1cm4gVGhlIGRlcHJlY2F0ZWRGaWVsZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBpbnQgZ2V0RGVwcmVjYXRlZEZpZWxkKCkgewogICAgICAgIHJldHVybiBkZXByZWNhdGVkRmllbGRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZXByZWNhdGVkRmllbGQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgc2V0RGVwcmVjYXRlZEZpZWxkKGludCB2YWx1ZSkgewoKICAgICAgICBkZXByZWNhdGVkRmllbGRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVwcmVjYXRlZEZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBkZXByZWNhdGVkRmllbGRfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZGVwcmVjYXRlZEZpZWxkMl8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgZGVwcmVjYXRlZF9maWVsZDIgPSAyIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQyIGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDUKICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkMiA9IDIgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDIgaXMgZGVwcmVjYXRlZC4KICAgICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NQogICAgICAgKiBAcmV0dXJuIFRoZSBkZXByZWNhdGVkRmllbGQyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGludCBnZXREZXByZWNhdGVkRmllbGQyKCkgewogICAgICAgIHJldHVybiBkZXByZWNhdGVkRmllbGQyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgZGVwcmVjYXRlZF9maWVsZDIgPSAyIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlcHJlY2F0ZWRGaWVsZDIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgc2V0RGVwcmVjYXRlZEZpZWxkMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZGVwcmVjYXRlZEZpZWxkMl8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGRlcHJlY2F0ZWRfZmllbGQyID0gMiBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVwcmVjYXRlZEZpZWxkMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgZGVwcmVjYXRlZEZpZWxkMl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3QgZGVwcmVjYXRlZEZpZWxkM18gPSAiIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZXByZWNhdGVkX2ZpZWxkMyA9IDMgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBkZXByZWNhdGVkIHByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDMgaXMgZGVwcmVjYXRlZC4KICAgICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlcHJlY2F0ZWRGaWVsZDMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDMoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQzIGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDYKICAgICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkMy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXREZXByZWNhdGVkRmllbGQzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVwcmVjYXRlZEZpZWxkM187CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IHM7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQzIGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDYKICAgICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlcHJlY2F0ZWRGaWVsZDMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0RGVwcmVjYXRlZEZpZWxkM0J5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVwcmVjYXRlZEZpZWxkM187CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDNfID0gYjsKICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlcHJlY2F0ZWRfZmllbGQzID0gMyBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZXByZWNhdGVkRmllbGQzIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBCdWlsZGVyIHNldERlcHJlY2F0ZWRGaWVsZDMoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlcHJlY2F0ZWRfZmllbGQzID0gMyBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVwcmVjYXRlZEZpZWxkMygpIHsKICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IGdldERlZmF1bHRJbnN0YW5jZSgpLmdldERlcHJlY2F0ZWRGaWVsZDMoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZXByZWNhdGVkX2ZpZWxkMyA9IDMgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIGRlcHJlY2F0ZWRGaWVsZDMgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgc2V0RGVwcmVjYXRlZEZpZWxkM0J5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZEZpZWxkNF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZU9yQnVpbGRlcj4gZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZF9maWVsZDQgPSA0IFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQ0IGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDcKICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQ0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQ0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZF9maWVsZDQgPSA0IFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAZGVwcmVjYXRlZCBwcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQ0IGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDcKICAgICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkNC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIGdldERlcHJlY2F0ZWRGaWVsZDQoKSB7CiAgICAgICAgaWYgKGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkNF8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGRlcHJlY2F0ZWRGaWVsZDRfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgQnVpbGRlciBzZXREZXByZWNhdGVkRmllbGQ0KGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0XyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZF9maWVsZDQgPSA0IFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBCdWlsZGVyIHNldERlcHJlY2F0ZWRGaWVsZDQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAoZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDRfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgbWVyZ2VEZXByZWNhdGVkRmllbGQ0KGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApICYmCiAgICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDRfICE9IG51bGwgJiYKICAgICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNF8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgIGdldERlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDRfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgIH0KICAgICAgICBpZiAoZGVwcmVjYXRlZEZpZWxkNF8gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgY2xlYXJEZXByZWNhdGVkRmllbGQ0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICBkZXByZWNhdGVkRmllbGQ0XyA9IG51bGw7CiAgICAgICAgaWYgKGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLkJ1aWxkZXIgZ2V0RGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXREZXByZWNhdGVkRmllbGQ0RmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZU9yQnVpbGRlciBnZXREZXByZWNhdGVkRmllbGQ0T3JCdWlsZGVyKCkgewogICAgICAgIGlmIChkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBkZXByZWNhdGVkRmllbGQ0XyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBkZXByZWNhdGVkRmllbGQ0XzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXREZXByZWNhdGVkRmllbGQ0RmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgZ2V0RGVwcmVjYXRlZEZpZWxkNCgpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNF8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0RGVwcmVjYXRlZExpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdERlcHJlY2F0ZWRMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdERlcHJlY2F0ZWRMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3REZXByZWNhdGVkTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdFBhcnNpbmdNZXJnZUxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy4KICAgICAgICAgIEV4dGVuZGFibGVNZXNzYWdlT3JCdWlsZGVyPFRlc3RQYXJzaW5nTWVyZ2VMaXRlPiB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIHJlcXVpcmVkQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc1JlcXVpcmVkQWxsVHlwZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkX2FsbF90eXBlcyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgcmVxdWlyZWRBbGxUeXBlcy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRSZXF1aXJlZEFsbFR5cGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRSZXF1aXJlZEFsbFR5cGVzT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsQWxsVHlwZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxBbGxUeXBlcy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRPcHRpb25hbEFsbFR5cGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbEFsbFR5cGVzT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IAogICAgICAgIGdldFJlcGVhdGVkQWxsVHlwZXNMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRSZXBlYXRlZEFsbFR5cGVzKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkQWxsVHlwZXNDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZEFsbFR5cGVzT3JCdWlsZGVyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRBbGxUeXBlc09yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsZ3JvdXAgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsR3JvdXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbGdyb3VwLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIGdldE9wdGlvbmFsR3JvdXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXIgZ2V0T3B0aW9uYWxHcm91cE9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXA+IAogICAgICAgIGdldFJlcGVhdGVkR3JvdXBMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIGdldFJlcGVhdGVkR3JvdXAoaW50IGluZGV4KTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEdyb3VwQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZEdyb3VwT3JCdWlsZGVyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cE9yQnVpbGRlciBnZXRSZXBlYXRlZEdyb3VwT3JCdWlsZGVyKAogICAgICAgIGludCBpbmRleCk7CiAgfQogIC8qKgogICAqIDxwcmU+CiAgICogU2VlIHRoZSBjb21tZW50cyBvZiB0aGUgc2FtZSB0eXBlIGluIHVuaXR0ZXN0LnByb3RvLgogICAqIDwvcHJlPgogICAqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdFBhcnNpbmdNZXJnZUxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlTWVzc2FnZTwKICAgICAgICBUZXN0UGFyc2luZ01lcmdlTGl0ZT4gaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZSkKICAgICAgVGVzdFBhcnNpbmdNZXJnZUxpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RQYXJzaW5nTWVyZ2VMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RQYXJzaW5nTWVyZ2VMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLCA/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0UGFyc2luZ01lcmdlTGl0ZSgpIHsKICAgICAgcmVwZWF0ZWRBbGxUeXBlc18gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkR3JvdXBfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RQYXJzaW5nTWVyZ2VMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIGludGVyZmFjZSBSZXBlYXRlZEZpZWxkc0dlbmVyYXRvck9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcikKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IAogICAgICAgICAgZ2V0RmllbGQxTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoaW50IGluZGV4KTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIGludCBnZXRGaWVsZDFDb3VudCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RmllbGQxT3JCdWlsZGVyTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDFPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IAogICAgICAgICAgZ2V0RmllbGQyTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDIoaW50IGluZGV4KTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIGludCBnZXRGaWVsZDJDb3VudCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RmllbGQyT3JCdWlsZGVyTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDJPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IAogICAgICAgICAgZ2V0RmllbGQzTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDMoaW50IGluZGV4KTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIGludCBnZXRGaWVsZDNDb3VudCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RmllbGQzT3JCdWlsZGVyTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDNPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDE+IAogICAgICAgICAgZ2V0R3JvdXAxTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBnZXRHcm91cDEoaW50IGluZGV4KTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBpbnQgZ2V0R3JvdXAxQ291bnQoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEdyb3VwMU9yQnVpbGRlckxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDFPckJ1aWxkZXIgZ2V0R3JvdXAxT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KTsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyPiAKICAgICAgICAgIGdldEdyb3VwMkxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgZ2V0R3JvdXAyKGludCBpbmRleCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgaW50IGdldEdyb3VwMkNvdW50KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRHcm91cDJPckJ1aWxkZXJMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyT3JCdWlsZGVyIGdldEdyb3VwMk9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCk7CgogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IAogICAgICAgICAgZ2V0RXh0MUxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEV4dDEoaW50IGluZGV4KTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBpbnQgZ2V0RXh0MUNvdW50KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RXh0MU9yQnVpbGRlckxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEV4dDFPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiAKICAgICAgICAgIGdldEV4dDJMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRFeHQyKGludCBpbmRleCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgaW50IGdldEV4dDJDb3VudCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEV4dDJPckJ1aWxkZXJMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRFeHQyT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IpCiAgICAgICAgUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JPckJ1aWxkZXIgewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAgIC8vIFVzZSBSZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgICBwcml2YXRlIFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgICB9CiAgICAgIHByaXZhdGUgUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IoKSB7CiAgICAgICAgZmllbGQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBmaWVsZDJfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGZpZWxkM18gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgZ3JvdXAxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBncm91cDJfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGV4dDFfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGV4dDJfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICByZXR1cm4gbmV3IFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwdWJsaWMgaW50ZXJmYWNlIEdyb3VwMU9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSkKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBmaWVsZDEgZmllbGQgaXMgc2V0LgogICAgICAgICAqLwogICAgICAgIGJvb2xlYW4gaGFzRmllbGQxKCk7CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDExOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBmaWVsZDEuCiAgICAgICAgICovCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoKTsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQxT3JCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDF9CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEdyb3VwMSBleHRlbmRzCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEpCiAgICAgICAgICBHcm91cDFPckJ1aWxkZXIgewogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgICAgICAvLyBVc2UgR3JvdXAxLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgICAgcHJpdmF0ZSBHcm91cDEoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBHcm91cDEoKSB7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICAgIHJldHVybiBuZXcgR3JvdXAxKCk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAxX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZJRUxEMV9GSUVMRF9OVU1CRVIgPSAxMTsKICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxXzsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZmllbGQxIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzRmllbGQxKCkgewogICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhlIGZpZWxkMS4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RmllbGQxKCkgewogICAgICAgICAgcmV0dXJuIGZpZWxkMV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBmaWVsZDFfOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDFPckJ1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gZmllbGQxXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGZpZWxkMV87CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDExLCBnZXRGaWVsZDEoKSk7CiAgICAgICAgICB9CiAgICAgICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgICAgICBzaXplID0gMDsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDExLCBnZXRGaWVsZDEoKSk7CiAgICAgICAgICB9CiAgICAgICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgICAgIHJldHVybiBzaXplOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEpKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEpIG9iajsKCiAgICAgICAgICBpZiAoaGFzRmllbGQxKCkgIT0gb3RoZXIuaGFzRmllbGQxKCkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGlmIChoYXNGaWVsZDEoKSkgewogICAgICAgICAgICBpZiAoIWdldEZpZWxkMSgpCiAgICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldEZpZWxkMSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICAgICAgfQogICAgICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICAgICAgaWYgKGhhc0ZpZWxkMSgpKSB7CiAgICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEZJRUxEMV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEZpZWxkMSgpLmhhc2hDb2RlKCk7CiAgICAgICAgICB9CiAgICAgICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICAgICAgcmV0dXJuIGhhc2g7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZUZyb20oCiAgICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZUZyb20oCiAgICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIHBhcnNlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZUZyb20oCiAgICAgICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VGcm9tKAogICAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZUZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZUZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcHJvdG90eXBlKSB7CiAgICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMX0KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxKQogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDFPckJ1aWxkZXIgewogICAgICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDFfZGVzY3JpcHRvcjsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgICAgfQoKICAgICAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEubmV3QnVpbGRlcigpCiAgICAgICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgICAgIH0KCiAgICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICAgICAgZ2V0RmllbGQxRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgICAgZmllbGQxXyA9IG51bGw7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMV9kZXNjcmlwdG9yOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIGJ1aWxkKCkgewogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEodGhpcyk7CiAgICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICAgIG9uQnVpbHQoKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgIH0KCiAgICAgICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcmVzdWx0KSB7CiAgICAgICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICAgICAgcmVzdWx0LmZpZWxkMV8gPSBmaWVsZDFCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgICAgID8gZmllbGQxXwogICAgICAgICAgICAgICAgICA6IGZpZWxkMUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEpIHsKICAgICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEpb3RoZXIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIG90aGVyKSB7CiAgICAgICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgICAgICBpZiAob3RoZXIuaGFzRmllbGQxKCkpIHsKICAgICAgICAgICAgICBtZXJnZUZpZWxkMShvdGhlci5nZXRGaWVsZDEoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgY2FzZSA5MDogewogICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICBnZXRGaWVsZDFGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0gLy8gY2FzZSA5MAogICAgICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDFfOwogICAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gZmllbGQxQnVpbGRlcl87CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGZpZWxkMSBmaWVsZCBpcyBzZXQuCiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBib29sZWFuIGhhc0ZpZWxkMSgpIHsKICAgICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAgICogQHJldHVybiBUaGUgZmllbGQxLgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoKSB7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkMV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBmaWVsZDFfOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDExOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQxKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGZpZWxkMV8gPSB2YWx1ZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDExOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQxKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICBmaWVsZDFfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRmllbGQxKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkgJiYKICAgICAgICAgICAgICAgIGZpZWxkMV8gIT0gbnVsbCAmJgogICAgICAgICAgICAgICAgZmllbGQxXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgICAgICBnZXRGaWVsZDFCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZmllbGQxXyA9IHZhbHVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChmaWVsZDFfICE9IG51bGwpIHsKICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQxKCkgewogICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgICAgIGZpZWxkMV8gPSBudWxsOwogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICBmaWVsZDFCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldEZpZWxkMUJ1aWxkZXIoKSB7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIHJldHVybiBnZXRGaWVsZDFGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEZpZWxkMU9yQnVpbGRlcigpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgICByZXR1cm4gZmllbGQxQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJldHVybiBmaWVsZDFfID09IG51bGwgPwogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogZmllbGQxXzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAgICovCiAgICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgICBnZXRGaWVsZDFGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgICAgIGdldEZpZWxkMSgpLAogICAgICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgICAgZmllbGQxXyA9IG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGZpZWxkMUJ1aWxkZXJfOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgICB9CgoKICAgICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEpCiAgICAgICAgfQoKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSkKICAgICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgREVGQVVMVF9JTlNUQU5DRTsKICAgICAgICBzdGF0aWMgewogICAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEoKTsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8R3JvdXAxPgogICAgICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxHcm91cDE+KCkgewogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEdyb3VwMSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgICAgIH0KICAgICAgICB9OwoKICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPEdyb3VwMT4gcGFyc2VyKCkgewogICAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8R3JvdXAxPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgICB9CgogICAgICB9CgogICAgICBwdWJsaWMgaW50ZXJmYWNlIEdyb3VwMk9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMikKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBmaWVsZDEgZmllbGQgaXMgc2V0LgogICAgICAgICAqLwogICAgICAgIGJvb2xlYW4gaGFzRmllbGQxKCk7CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBmaWVsZDEuCiAgICAgICAgICovCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoKTsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQxT3JCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDJ9CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEdyb3VwMiBleHRlbmRzCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIpCiAgICAgICAgICBHcm91cDJPckJ1aWxkZXIgewogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgICAgICAvLyBVc2UgR3JvdXAyLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgICAgcHJpdmF0ZSBHcm91cDIoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBHcm91cDIoKSB7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICAgIHJldHVybiBuZXcgR3JvdXAyKCk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAyX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZJRUxEMV9GSUVMRF9OVU1CRVIgPSAyMTsKICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxXzsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZmllbGQxIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzRmllbGQxKCkgewogICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhlIGZpZWxkMS4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RmllbGQxKCkgewogICAgICAgICAgcmV0dXJuIGZpZWxkMV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBmaWVsZDFfOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDFPckJ1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gZmllbGQxXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGZpZWxkMV87CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDIxLCBnZXRGaWVsZDEoKSk7CiAgICAgICAgICB9CiAgICAgICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgICAgICBzaXplID0gMDsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDIxLCBnZXRGaWVsZDEoKSk7CiAgICAgICAgICB9CiAgICAgICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgICAgIHJldHVybiBzaXplOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIpKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIpIG9iajsKCiAgICAgICAgICBpZiAoaGFzRmllbGQxKCkgIT0gb3RoZXIuaGFzRmllbGQxKCkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGlmIChoYXNGaWVsZDEoKSkgewogICAgICAgICAgICBpZiAoIWdldEZpZWxkMSgpCiAgICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldEZpZWxkMSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICAgICAgfQogICAgICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICAgICAgaWYgKGhhc0ZpZWxkMSgpKSB7CiAgICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEZJRUxEMV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEZpZWxkMSgpLmhhc2hDb2RlKCk7CiAgICAgICAgICB9CiAgICAgICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICAgICAgcmV0dXJuIGhhc2g7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZUZyb20oCiAgICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZUZyb20oCiAgICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHBhcnNlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZUZyb20oCiAgICAgICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VGcm9tKAogICAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZUZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZUZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcHJvdG90eXBlKSB7CiAgICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMn0KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyKQogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDJPckJ1aWxkZXIgewogICAgICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDJfZGVzY3JpcHRvcjsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgICAgfQoKICAgICAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIubmV3QnVpbGRlcigpCiAgICAgICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgICAgIH0KCiAgICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICAgICAgZ2V0RmllbGQxRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgICAgZmllbGQxXyA9IG51bGw7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMl9kZXNjcmlwdG9yOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMi5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIGJ1aWxkKCkgewogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIodGhpcyk7CiAgICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICAgIG9uQnVpbHQoKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgIH0KCiAgICAgICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcmVzdWx0KSB7CiAgICAgICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICAgICAgcmVzdWx0LmZpZWxkMV8gPSBmaWVsZDFCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgICAgID8gZmllbGQxXwogICAgICAgICAgICAgICAgICA6IGZpZWxkMUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIpIHsKICAgICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIpb3RoZXIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIG90aGVyKSB7CiAgICAgICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgICAgICBpZiAob3RoZXIuaGFzRmllbGQxKCkpIHsKICAgICAgICAgICAgICBtZXJnZUZpZWxkMShvdGhlci5nZXRGaWVsZDEoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgY2FzZSAxNzA6IHsKICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgICAgZ2V0RmllbGQxRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9IC8vIGNhc2UgMTcwCiAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMV87CiAgICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiBmaWVsZDFCdWlsZGVyXzsKICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZmllbGQxIGZpZWxkIGlzIHNldC4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzRmllbGQxKCkgewogICAgICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICAgKiBAcmV0dXJuIFRoZSBmaWVsZDEuCiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEZpZWxkMSgpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICByZXR1cm4gZmllbGQxXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGZpZWxkMV87CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkMUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZDEoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZmllbGQxXyA9IHZhbHVlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZDEoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgIGZpZWxkMV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGaWVsZDEoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSAmJgogICAgICAgICAgICAgICAgZmllbGQxXyAhPSBudWxsICYmCiAgICAgICAgICAgICAgICBmaWVsZDFfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgICAgIGdldEZpZWxkMUJ1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmaWVsZDFfID0gdmFsdWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGZpZWxkMV8gIT0gbnVsbCkgewogICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZDEoKSB7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgICAgZmllbGQxXyA9IG51bGw7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgZ2V0RmllbGQxQnVpbGRlcigpIHsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgcmV0dXJuIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQxT3JCdWlsZGVyKCkgewogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkMV8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBmaWVsZDFfOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICAgIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICBmaWVsZDFCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICAgICAgZ2V0RmllbGQxKCksCiAgICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgICAgICBmaWVsZDFfID0gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmllbGQxQnVpbGRlcl87CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICAgIH0KCgogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMikKICAgICAgICB9CgogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyKQogICAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBERUZBVUxUX0lOU1RBTkNFOwogICAgICAgIHN0YXRpYyB7CiAgICAgICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMigpOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxHcm91cDI+CiAgICAgICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPEdyb3VwMj4oKSB7CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgR3JvdXAyIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICAgICAgfQogICAgICAgIH07CgogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8R3JvdXAyPiBwYXJzZXIoKSB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxHcm91cDI+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICAgIH0KCiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZJRUxEMV9GSUVMRF9OVU1CRVIgPSAxOwogICAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBmaWVsZDFfOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZ2V0RmllbGQxTGlzdCgpIHsKICAgICAgICByZXR1cm4gZmllbGQxXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RmllbGQxT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZmllbGQxXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEZpZWxkMUNvdW50KCkgewogICAgICAgIHJldHVybiBmaWVsZDFfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGZpZWxkMV8uZ2V0KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDFPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZmllbGQxXy5nZXQoaW5kZXgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBGSUVMRDJfRklFTERfTlVNQkVSID0gMjsKICAgICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZmllbGQyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldEZpZWxkMkxpc3QoKSB7CiAgICAgICAgcmV0dXJuIGZpZWxkMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEZpZWxkMk9yQnVpbGRlckxpc3QoKSB7CiAgICAgICAgcmV0dXJuIGZpZWxkMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRGaWVsZDJDb3VudCgpIHsKICAgICAgICByZXR1cm4gZmllbGQyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RmllbGQyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBmaWVsZDJfLmdldChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQyT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGZpZWxkMl8uZ2V0KGluZGV4KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRklFTEQzX0ZJRUxEX05VTUJFUiA9IDM7CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGZpZWxkM187CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRGaWVsZDNMaXN0KCkgewogICAgICAgIHJldHVybiBmaWVsZDNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRGaWVsZDNPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIHJldHVybiBmaWVsZDNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RmllbGQzQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGZpZWxkM18uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEZpZWxkMyhpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZmllbGQzXy5nZXQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEZpZWxkM09yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBmaWVsZDNfLmdldChpbmRleCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEdST1VQMV9GSUVMRF9OVU1CRVIgPSAxMDsKICAgICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxPiBncm91cDFfOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMT4gZ2V0R3JvdXAxTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ3JvdXAxXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDFPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0R3JvdXAxT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ3JvdXAxXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRHcm91cDFDb3VudCgpIHsKICAgICAgICByZXR1cm4gZ3JvdXAxXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgZ2V0R3JvdXAxKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBncm91cDFfLmdldChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDFPckJ1aWxkZXIgZ2V0R3JvdXAxT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdyb3VwMV8uZ2V0KGluZGV4KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgR1JPVVAyX0ZJRUxEX05VTUJFUiA9IDIwOwogICAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDI+IGdyb3VwMl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyPiBnZXRHcm91cDJMaXN0KCkgewogICAgICAgIHJldHVybiBncm91cDJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRHcm91cDJPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIHJldHVybiBncm91cDJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEdyb3VwMkNvdW50KCkgewogICAgICAgIHJldHVybiBncm91cDJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBnZXRHcm91cDIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdyb3VwMl8uZ2V0KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlciBnZXRHcm91cDJPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ3JvdXAyXy5nZXQoaW5kZXgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFWFQxX0ZJRUxEX05VTUJFUiA9IDEwMDA7CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGV4dDFfOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldEV4dDFMaXN0KCkgewogICAgICAgIHJldHVybiBleHQxXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEV4dDFPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIHJldHVybiBleHQxXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRFeHQxQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGV4dDFfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RXh0MShpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZXh0MV8uZ2V0KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RXh0MU9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBleHQxXy5nZXQoaW5kZXgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFWFQyX0ZJRUxEX05VTUJFUiA9IDEwMDE7CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGV4dDJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldEV4dDJMaXN0KCkgewogICAgICAgIHJldHVybiBleHQyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEV4dDJPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIHJldHVybiBleHQyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRFeHQyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGV4dDJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RXh0MihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZXh0Ml8uZ2V0KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RXh0Mk9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBleHQyXy5nZXQoaW5kZXgpOwogICAgICB9CgogICAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZmllbGQxXy5zaXplKCk7IGkrKykgewogICAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxLCBmaWVsZDFfLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZmllbGQyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgyLCBmaWVsZDJfLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZmllbGQzXy5zaXplKCk7IGkrKykgewogICAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgzLCBmaWVsZDNfLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZ3JvdXAxXy5zaXplKCk7IGkrKykgewogICAgICAgICAgb3V0cHV0LndyaXRlR3JvdXAoMTAsIGdyb3VwMV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBncm91cDJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVHcm91cCgyMCwgZ3JvdXAyXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGV4dDFfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDEwMDAsIGV4dDFfLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZXh0Ml8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMTAwMSwgZXh0Ml8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgICAgc2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBmaWVsZDFfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxLCBmaWVsZDFfLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZmllbGQyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMiwgZmllbGQyXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGZpZWxkM18uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDMsIGZpZWxkM18uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBncm91cDFfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVHcm91cFNpemUoMTAsIGdyb3VwMV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBncm91cDJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVHcm91cFNpemUoMjAsIGdyb3VwMl8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBleHQxXy5zaXplKCk7IGkrKykgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTAwMCwgZXh0MV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBleHQyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTAwMSwgZXh0Ml8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICAgIHJldHVybiBzaXplOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IpKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgICAgfQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKSBvYmo7CgogICAgICAgIGlmICghZ2V0RmllbGQxTGlzdCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RmllbGQxTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmICghZ2V0RmllbGQyTGlzdCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RmllbGQyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmICghZ2V0RmllbGQzTGlzdCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RmllbGQzTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmICghZ2V0R3JvdXAxTGlzdCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0R3JvdXAxTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmICghZ2V0R3JvdXAyTGlzdCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0R3JvdXAyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmICghZ2V0RXh0MUxpc3QoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldEV4dDFMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKCFnZXRFeHQyTGlzdCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RXh0Mkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgICAgfQogICAgICAgIGludCBoYXNoID0gNDE7CiAgICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgICAgaWYgKGdldEZpZWxkMUNvdW50KCkgPiAwKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBGSUVMRDFfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RmllbGQxTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgICAgfQogICAgICAgIGlmIChnZXRGaWVsZDJDb3VudCgpID4gMCkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgRklFTEQyX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEZpZWxkMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICAgIH0KICAgICAgICBpZiAoZ2V0RmllbGQzQ291bnQoKSA+IDApIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEZJRUxEM19GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRGaWVsZDNMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKGdldEdyb3VwMUNvdW50KCkgPiAwKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBHUk9VUDFfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0R3JvdXAxTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgICAgfQogICAgICAgIGlmIChnZXRHcm91cDJDb3VudCgpID4gMCkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgR1JPVVAyX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEdyb3VwMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICAgIH0KICAgICAgICBpZiAoZ2V0RXh0MUNvdW50KCkgPiAwKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBFWFQxX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEV4dDFMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKGdldEV4dDJDb3VudCgpID4gMCkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgRVhUMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRFeHQyTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgICAgfQogICAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICAgIHJldHVybiBoYXNoOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlRnJvbSgKICAgICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHByb3RvdHlwZSkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcn0KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JPckJ1aWxkZXIgewogICAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgIH0KCiAgICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLm5ld0J1aWxkZXIoKQogICAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZmllbGQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMV8gPSBudWxsOwogICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZmllbGQyXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMl8gPSBudWxsOwogICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZmllbGQzXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkM18gPSBudWxsOwogICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZ3JvdXAxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMV8gPSBudWxsOwogICAgICAgICAgICBncm91cDFCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDgpOwogICAgICAgICAgaWYgKGdyb3VwMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZ3JvdXAyXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMl8gPSBudWxsOwogICAgICAgICAgICBncm91cDJCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGV4dDFfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MV8gPSBudWxsOwogICAgICAgICAgICBleHQxQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDIwKTsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBleHQyXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDJfID0gbnVsbDsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgICB9CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgYnVpbGQoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKHRoaXMpOwogICAgICAgICAgYnVpbGRQYXJ0aWFsUmVwZWF0ZWRGaWVsZHMocmVzdWx0KTsKICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbFJlcGVhdGVkRmllbGRzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHJlc3VsdCkgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICAgICAgZmllbGQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGZpZWxkMV8pOwogICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXN1bHQuZmllbGQxXyA9IGZpZWxkMV87CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQuZmllbGQxXyA9IGZpZWxkMUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgICAgICBmaWVsZDJfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZmllbGQyXyk7CiAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlc3VsdC5maWVsZDJfID0gZmllbGQyXzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlc3VsdC5maWVsZDJfID0gZmllbGQyQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgICAgIGZpZWxkM18gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChmaWVsZDNfKTsKICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0LmZpZWxkM18gPSBmaWVsZDNfOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVzdWx0LmZpZWxkM18gPSBmaWVsZDNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApKSB7CiAgICAgICAgICAgICAgZ3JvdXAxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGdyb3VwMV8pOwogICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXN1bHQuZ3JvdXAxXyA9IGdyb3VwMV87CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQuZ3JvdXAxXyA9IGdyb3VwMUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZ3JvdXAyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICAgICAgICBncm91cDJfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZ3JvdXAyXyk7CiAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlc3VsdC5ncm91cDJfID0gZ3JvdXAyXzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlc3VsdC5ncm91cDJfID0gZ3JvdXAyQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgICAgICBleHQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGV4dDFfKTsKICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAyMCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0LmV4dDFfID0gZXh0MV87CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQuZXh0MV8gPSBleHQxQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICAgICAgICBleHQyXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGV4dDJfKTsKICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0LmV4dDJfID0gZXh0Ml87CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQuZXh0Ml8gPSBleHQyQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHJlc3VsdCkgewogICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcikgewogICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcilvdGhlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZmllbGQxXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBpZiAoZmllbGQxXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGZpZWxkMV8gPSBvdGhlci5maWVsZDFfOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBlbnN1cmVGaWVsZDFJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIGZpZWxkMV8uYWRkQWxsKG90aGVyLmZpZWxkMV8pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCFvdGhlci5maWVsZDFfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICAgIGZpZWxkMV8gPSBvdGhlci5maWVsZDFfOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICAgIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIuZmllbGQxXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoIW90aGVyLmZpZWxkMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGZpZWxkMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBmaWVsZDJfID0gb3RoZXIuZmllbGQyXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZW5zdXJlRmllbGQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBmaWVsZDJfLmFkZEFsbChvdGhlci5maWVsZDJfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZmllbGQyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgICBmaWVsZDJCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgICBmaWVsZDJfID0gb3RoZXIuZmllbGQyXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMgPwogICAgICAgICAgICAgICAgICAgICBnZXRGaWVsZDJGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLmZpZWxkMl8pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKCFvdGhlci5maWVsZDNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChmaWVsZDNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgZmllbGQzXyA9IG90aGVyLmZpZWxkM187CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGVuc3VyZUZpZWxkM0lzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgZmllbGQzXy5hZGRBbGwob3RoZXIuZmllbGQzXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAoIW90aGVyLmZpZWxkM18uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICAgICAgZmllbGQzXyA9IG90aGVyLmZpZWxkM187CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICAgICAgICBmaWVsZDNCdWlsZGVyXyA9IAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgICAgZ2V0RmllbGQzRmllbGRCdWlsZGVyKCkgOiBudWxsOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyhvdGhlci5maWVsZDNfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChncm91cDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZ3JvdXAxXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBpZiAoZ3JvdXAxXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGdyb3VwMV8gPSBvdGhlci5ncm91cDFfOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDgpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBlbnN1cmVHcm91cDFJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIGdyb3VwMV8uYWRkQWxsKG90aGVyLmdyb3VwMV8pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCFvdGhlci5ncm91cDFfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChncm91cDFCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGdyb3VwMUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICAgIGdyb3VwMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICAgIGdyb3VwMV8gPSBvdGhlci5ncm91cDFfOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDgpOwogICAgICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICAgIGdldEdyb3VwMUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIuZ3JvdXAxXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZ3JvdXAyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoIW90aGVyLmdyb3VwMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGdyb3VwMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBncm91cDJfID0gb3RoZXIuZ3JvdXAyXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZW5zdXJlR3JvdXAySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBncm91cDJfLmFkZEFsbChvdGhlci5ncm91cDJfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZ3JvdXAyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBpZiAoZ3JvdXAyQnVpbGRlcl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBncm91cDJCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgICBncm91cDJCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgICBncm91cDJfID0gb3RoZXIuZ3JvdXAyXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMgPwogICAgICAgICAgICAgICAgICAgICBnZXRHcm91cDJGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLmdyb3VwMl8pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZXh0MV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGV4dDFfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgZXh0MV8gPSBvdGhlci5leHQxXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDIwKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZW5zdXJlRXh0MUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgZXh0MV8uYWRkQWxsKG90aGVyLmV4dDFfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZXh0MV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgICBleHQxQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICAgICAgZXh0MV8gPSBvdGhlci5leHQxXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDIwKTsKICAgICAgICAgICAgICAgIGV4dDFCdWlsZGVyXyA9IAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgICAgZ2V0RXh0MUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZXh0MUJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLmV4dDFfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoIW90aGVyLmV4dDJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChleHQyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGV4dDJfID0gb3RoZXIuZXh0Ml87CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGVuc3VyZUV4dDJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIGV4dDJfLmFkZEFsbChvdGhlci5leHQyXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAoIW90aGVyLmV4dDJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBleHQyQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgICAgZXh0MkJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICAgIGV4dDJfID0gb3RoZXIuZXh0Ml87CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgICAgICAgICBleHQyQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICAgIGdldEV4dDJGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyhvdGhlci5leHQyXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDEwOiB7CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgbSA9CiAgICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlBBUlNFUiwKICAgICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgZW5zdXJlRmllbGQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgZmllbGQxXy5hZGQobSk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uYWRkTWVzc2FnZShtKTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxMAogICAgICAgICAgICAgICAgY2FzZSAxODogewogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgIGVuc3VyZUZpZWxkMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICAgIGZpZWxkMl8uYWRkKG0pOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZE1lc3NhZ2UobSk7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgMTgKICAgICAgICAgICAgICAgIGNhc2UgMjY6IHsKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBtID0KICAgICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVGaWVsZDNJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgICBmaWVsZDNfLmFkZChtKTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDI2CiAgICAgICAgICAgICAgICBjYXNlIDgzOiB7CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBtID0KICAgICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRHcm91cCgxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVHcm91cDFJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgICBncm91cDFfLmFkZChtKTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBncm91cDFCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDgzCiAgICAgICAgICAgICAgICBjYXNlIDE2MzogewogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgbSA9CiAgICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLlBBUlNFUiwKICAgICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgZW5zdXJlR3JvdXAySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgZ3JvdXAyXy5hZGQobSk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgZ3JvdXAyQnVpbGRlcl8uYWRkTWVzc2FnZShtKTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjMKICAgICAgICAgICAgICAgIGNhc2UgODAwMjogewogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgICBpZiAoZXh0MUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVFeHQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgZXh0MV8uYWRkKG0pOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDgwMDIKICAgICAgICAgICAgICAgIGNhc2UgODAxMDogewogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgZXh0Ml8uYWRkKG0pOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDgwMTAKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZmllbGQxXyA9CiAgICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZUZpZWxkMUlzTXV0YWJsZSgpIHsKICAgICAgICAgIGlmICghKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgZmllbGQxXyA9IG5ldyBqYXZhLnV0aWwuQXJyYXlMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+KGZpZWxkMV8pOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gZmllbGQxQnVpbGRlcl87CgogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZ2V0RmllbGQxTGlzdCgpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChmaWVsZDFfKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRNZXNzYWdlTGlzdCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGludCBnZXRGaWVsZDFDb3VudCgpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDFfLnNpemUoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRDb3VudCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RmllbGQxKGludCBpbmRleCkgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMV8uZ2V0KGluZGV4KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRNZXNzYWdlKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkMSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMUlzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDFfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQxKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMUlzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDFfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRmllbGQxKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlRmllbGQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMV8uYWRkKHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRmllbGQxKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlRmllbGQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMV8uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRGaWVsZDEoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMUlzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDFfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uYWRkTWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEZpZWxkMSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDFJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQxXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbEZpZWxkMSgKICAgICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiB2YWx1ZXMpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMUlzTXV0YWJsZSgpOwogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgICAgICB2YWx1ZXMsIGZpZWxkMV8pOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKHZhbHVlcyk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQxKCkgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZmllbGQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZUZpZWxkMShpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMUlzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDFfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRGaWVsZDFCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIHJldHVybiBnZXRGaWVsZDFGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEZpZWxkMU9yQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZmllbGQxXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgIGdldEZpZWxkMU9yQnVpbGRlckxpc3QoKSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZmllbGQxQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChmaWVsZDFfKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYWRkRmllbGQxQnVpbGRlcigpIHsKICAgICAgICAgIHJldHVybiBnZXRGaWVsZDFGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRGaWVsZDFCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIHJldHVybiBnZXRGaWVsZDFGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICAgIGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXI+IAogICAgICAgICAgICAgZ2V0RmllbGQxQnVpbGRlckxpc3QoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0RmllbGQxRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICAgIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgICAgZmllbGQxXywKICAgICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgIGZpZWxkMV8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGZpZWxkMUJ1aWxkZXJfOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBmaWVsZDJfID0KICAgICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBwcml2YXRlIHZvaWQgZW5zdXJlRmllbGQySXNNdXRhYmxlKCkgewogICAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgICBmaWVsZDJfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4oZmllbGQyXyk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiBmaWVsZDJCdWlsZGVyXzsKCiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRGaWVsZDJMaXN0KCkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGZpZWxkMl8pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMkJ1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgaW50IGdldEZpZWxkMkNvdW50KCkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMl8uc2l6ZSgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMkJ1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDIoaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZmllbGQyXy5nZXQoaW5kZXgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMkJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQyKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlRmllbGQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMl8uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQyQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMl8uc2V0KGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQyQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRGaWVsZDIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVGaWVsZDJJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQyXy5hZGQodmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRGaWVsZDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVGaWVsZDJJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQyXy5hZGQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEZpZWxkMigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMl8uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5hZGRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRmllbGQyKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMklzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDJfLmFkZChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsRmllbGQyKAogICAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IHZhbHVlcykgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICAgIHZhbHVlcywgZmllbGQyXyk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQyQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZDIoKSB7CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBmaWVsZDJfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQyQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlRmllbGQyKGludCBpbmRleCkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldEZpZWxkMkJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGdldEZpZWxkMkZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoaW5kZXgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQyT3JCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDJfLmdldChpbmRleCk7ICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmllbGQyQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcihpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICAgZ2V0RmllbGQyT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDJCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGZpZWxkMl8pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRGaWVsZDJCdWlsZGVyKCkgewogICAgICAgICAgcmV0dXJuIGdldEZpZWxkMkZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGFkZEZpZWxkMkJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGdldEZpZWxkMkZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRGaWVsZDJCdWlsZGVyTGlzdCgpIHsKICAgICAgICAgIHJldHVybiBnZXRGaWVsZDJGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyTGlzdCgpOwogICAgICAgIH0KICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgZ2V0RmllbGQyRmllbGRCdWlsZGVyKCkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZmllbGQyQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgICBmaWVsZDJfLAogICAgICAgICAgICAgICAgICAgICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApLAogICAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgICAgZmllbGQyXyA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZmllbGQyQnVpbGRlcl87CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGZpZWxkM18gPQogICAgICAgICAgamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVGaWVsZDNJc011dGFibGUoKSB7CiAgICAgICAgICBpZiAoISgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgICAgIGZpZWxkM18gPSBuZXcgamF2YS51dGlsLkFycmF5TGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPihmaWVsZDNfKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IGZpZWxkM0J1aWxkZXJfOwoKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldEZpZWxkM0xpc3QoKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZmllbGQzXyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmllbGQzQnVpbGRlcl8uZ2V0TWVzc2FnZUxpc3QoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBpbnQgZ2V0RmllbGQzQ291bnQoKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZmllbGQzXy5zaXplKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmllbGQzQnVpbGRlcl8uZ2V0Q291bnQoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEZpZWxkMyhpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDNfLmdldChpbmRleCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmllbGQzQnVpbGRlcl8uZ2V0TWVzc2FnZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZDMoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVGaWVsZDNJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQzXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkMygKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDNJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQzXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEZpZWxkMyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUZpZWxkM0lzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDNfLmFkZCh2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uYWRkTWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEZpZWxkMygKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUZpZWxkM0lzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDNfLmFkZChpbmRleCwgdmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkM0J1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRmllbGQzKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDNJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQzXy5hZGQoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkM0J1aWxkZXJfLmFkZE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRGaWVsZDMoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQzSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkM18uYWRkKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxGaWVsZDMoCiAgICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDNJc011dGFibGUoKTsKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgICAgdmFsdWVzLCBmaWVsZDNfKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyh2YWx1ZXMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkMygpIHsKICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGZpZWxkM18gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVGaWVsZDMoaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDNJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQzXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkM0J1aWxkZXJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgZ2V0RmllbGQzQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0RmllbGQzRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDNPckJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkM18uZ2V0KGluZGV4KTsgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDNCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRGaWVsZDNPckJ1aWxkZXJMaXN0KCkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkM0J1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZmllbGQzXyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGFkZEZpZWxkM0J1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0RmllbGQzRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYWRkRmllbGQzQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0RmllbGQzRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyPiAKICAgICAgICAgICAgIGdldEZpZWxkM0J1aWxkZXJMaXN0KCkgewogICAgICAgICAgcmV0dXJuIGdldEZpZWxkM0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXJMaXN0KCk7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICBnZXRGaWVsZDNGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBmaWVsZDNCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICAgIGZpZWxkM18sCiAgICAgICAgICAgICAgICAgICAgKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCksCiAgICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgICBmaWVsZDNfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBmaWVsZDNCdWlsZGVyXzsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxPiBncm91cDFfID0KICAgICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBwcml2YXRlIHZvaWQgZW5zdXJlR3JvdXAxSXNNdXRhYmxlKCkgewogICAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgICAgICBncm91cDFfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxPihncm91cDFfKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDFPckJ1aWxkZXI+IGdyb3VwMUJ1aWxkZXJfOwoKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDEgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDE+IGdldEdyb3VwMUxpc3QoKSB7CiAgICAgICAgICBpZiAoZ3JvdXAxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZ3JvdXAxXyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZ3JvdXAxQnVpbGRlcl8uZ2V0TWVzc2FnZUxpc3QoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgaW50IGdldEdyb3VwMUNvdW50KCkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGdyb3VwMV8uc2l6ZSgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGdyb3VwMUJ1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBnZXRHcm91cDEoaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZ3JvdXAxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZ3JvdXAxXy5nZXQoaW5kZXgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGdyb3VwMUJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDEgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEdyb3VwMSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgdmFsdWUpIHsKICAgICAgICAgIGlmIChncm91cDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlR3JvdXAxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGdyb3VwMV8uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0R3JvdXAxKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlR3JvdXAxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGdyb3VwMV8uc2V0KGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkR3JvdXAxKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSB2YWx1ZSkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVHcm91cDFJc011dGFibGUoKTsKICAgICAgICAgICAgZ3JvdXAxXy5hZGQodmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMUJ1aWxkZXJfLmFkZE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkR3JvdXAxKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSB2YWx1ZSkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVHcm91cDFJc011dGFibGUoKTsKICAgICAgICAgICAgZ3JvdXAxXy5hZGQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBncm91cDFCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRHcm91cDEoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlR3JvdXAxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGdyb3VwMV8uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBncm91cDFCdWlsZGVyXy5hZGRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDEgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEdyb3VwMSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChncm91cDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUdyb3VwMUlzTXV0YWJsZSgpOwogICAgICAgICAgICBncm91cDFfLmFkZChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMUJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDEgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbEdyb3VwMSgKICAgICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDE+IHZhbHVlcykgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlR3JvdXAxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICAgIHZhbHVlcywgZ3JvdXAxXyk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDEgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyR3JvdXAxKCkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZ3JvdXAxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDgpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVHcm91cDEoaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZ3JvdXAxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVHcm91cDFJc011dGFibGUoKTsKICAgICAgICAgICAgZ3JvdXAxXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMUJ1aWxkZXJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxLkJ1aWxkZXIgZ2V0R3JvdXAxQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0R3JvdXAxRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMU9yQnVpbGRlciBnZXRHcm91cDFPckJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGdyb3VwMV8uZ2V0KGluZGV4KTsgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBncm91cDFCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMU9yQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRHcm91cDFPckJ1aWxkZXJMaXN0KCkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGdyb3VwMUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZ3JvdXAxXyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5CdWlsZGVyIGFkZEdyb3VwMUJ1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0R3JvdXAxRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDEgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuQnVpbGRlciBhZGRHcm91cDFCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIHJldHVybiBnZXRHcm91cDFGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICAgIGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDEgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRHcm91cDFCdWlsZGVyTGlzdCgpIHsKICAgICAgICAgIHJldHVybiBnZXRHcm91cDFGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyTGlzdCgpOwogICAgICAgIH0KICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxT3JCdWlsZGVyPiAKICAgICAgICAgICAgZ2V0R3JvdXAxRmllbGRCdWlsZGVyKCkgewogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgICBncm91cDFfLAogICAgICAgICAgICAgICAgICAgICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApLAogICAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgICAgZ3JvdXAxXyA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZ3JvdXAxQnVpbGRlcl87CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMj4gZ3JvdXAyXyA9CiAgICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZUdyb3VwMklzTXV0YWJsZSgpIHsKICAgICAgICAgIGlmICghKChiaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICAgICAgZ3JvdXAyXyA9IG5ldyBqYXZhLnV0aWwuQXJyYXlMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMj4oZ3JvdXAyXyk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyT3JCdWlsZGVyPiBncm91cDJCdWlsZGVyXzsKCiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyPiBnZXRHcm91cDJMaXN0KCkgewogICAgICAgICAgaWYgKGdyb3VwMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGdyb3VwMl8pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGdyb3VwMkJ1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGludCBnZXRHcm91cDJDb3VudCgpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBncm91cDJfLnNpemUoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBncm91cDJCdWlsZGVyXy5nZXRDb3VudCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgZ2V0R3JvdXAyKGludCBpbmRleCkgewogICAgICAgICAgaWYgKGdyb3VwMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGdyb3VwMl8uZ2V0KGluZGV4KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBncm91cDJCdWlsZGVyXy5nZXRNZXNzYWdlKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRHcm91cDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZ3JvdXAyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUdyb3VwMklzTXV0YWJsZSgpOwogICAgICAgICAgICBncm91cDJfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEdyb3VwMigKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUdyb3VwMklzTXV0YWJsZSgpOwogICAgICAgICAgICBncm91cDJfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEdyb3VwMihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgdmFsdWUpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlR3JvdXAySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGdyb3VwMl8uYWRkKHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBncm91cDJCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEdyb3VwMigKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgdmFsdWUpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlR3JvdXAySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGdyb3VwMl8uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZ3JvdXAyQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkR3JvdXAyKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUdyb3VwMklzTXV0YWJsZSgpOwogICAgICAgICAgICBncm91cDJfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZ3JvdXAyQnVpbGRlcl8uYWRkTWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRHcm91cDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZ3JvdXAyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVHcm91cDJJc011dGFibGUoKTsKICAgICAgICAgICAgZ3JvdXAyXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBncm91cDJCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxHcm91cDIoCiAgICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyPiB2YWx1ZXMpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUdyb3VwMklzTXV0YWJsZSgpOwogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgICAgICB2YWx1ZXMsIGdyb3VwMl8pOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKHZhbHVlcyk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckdyb3VwMigpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGdyb3VwMl8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBncm91cDJCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlR3JvdXAyKGludCBpbmRleCkgewogICAgICAgICAgaWYgKGdyb3VwMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlR3JvdXAySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGdyb3VwMl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBncm91cDJCdWlsZGVyXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMi5CdWlsZGVyIGdldEdyb3VwMkJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGdldEdyb3VwMkZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoaW5kZXgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDJPckJ1aWxkZXIgZ2V0R3JvdXAyT3JCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBncm91cDJfLmdldChpbmRleCk7ICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZ3JvdXAyQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcihpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDJPckJ1aWxkZXI+IAogICAgICAgICAgICAgZ2V0R3JvdXAyT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBncm91cDJCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGdyb3VwMl8pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIuQnVpbGRlciBhZGRHcm91cDJCdWlsZGVyKCkgewogICAgICAgICAgcmV0dXJuIGdldEdyb3VwMkZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIgYWRkR3JvdXAyQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0R3JvdXAyRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXI+IAogICAgICAgICAgICAgZ2V0R3JvdXAyQnVpbGRlckxpc3QoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0R3JvdXAyRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlcj4gCiAgICAgICAgICAgIGdldEdyb3VwMkZpZWxkQnVpbGRlcigpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgICAgZ3JvdXAyXywKICAgICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgIGdyb3VwMl8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGdyb3VwMkJ1aWxkZXJfOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBleHQxXyA9CiAgICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZUV4dDFJc011dGFibGUoKSB7CiAgICAgICAgICBpZiAoISgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgICAgIGV4dDFfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4oZXh0MV8pOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gZXh0MUJ1aWxkZXJfOwoKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRFeHQxTGlzdCgpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZXh0MV8pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDFCdWlsZGVyXy5nZXRNZXNzYWdlTGlzdCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBpbnQgZ2V0RXh0MUNvdW50KCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBleHQxXy5zaXplKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZXh0MUJ1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RXh0MShpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZXh0MV8uZ2V0KGluZGV4KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBleHQxQnVpbGRlcl8uZ2V0TWVzc2FnZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RXh0MSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVFeHQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDFfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRFeHQxKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVFeHQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDFfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRFeHQxKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUV4dDFJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0MV8uYWRkKHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQxQnVpbGRlcl8uYWRkTWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRFeHQxKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUV4dDFJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0MV8uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MUJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEV4dDEoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVFeHQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDFfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MUJ1aWxkZXJfLmFkZE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRXh0MSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRXh0MUlzTXV0YWJsZSgpOwogICAgICAgICAgICBleHQxXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQxQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsRXh0MSgKICAgICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiB2YWx1ZXMpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVFeHQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICAgIHZhbHVlcywgZXh0MV8pOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyh2YWx1ZXMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJFeHQxKCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGV4dDFfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAyMCk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVFeHQxKGludCBpbmRleCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUV4dDFJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0MV8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQxQnVpbGRlcl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgZ2V0RXh0MUJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGdldEV4dDFGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRFeHQxT3JCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZXh0MV8uZ2V0KGluZGV4KTsgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBleHQxQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcihpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgIGdldEV4dDFPckJ1aWxkZXJMaXN0KCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBleHQxQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChleHQxXyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRFeHQxQnVpbGRlcigpIHsKICAgICAgICAgIHJldHVybiBnZXRFeHQxRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGFkZEV4dDFCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIHJldHVybiBnZXRFeHQxRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRFeHQxQnVpbGRlckxpc3QoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0RXh0MUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXJMaXN0KCk7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICBnZXRFeHQxRmllbGRCdWlsZGVyKCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGV4dDFCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICAgIGV4dDFfLAogICAgICAgICAgICAgICAgICAgICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApLAogICAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgICAgZXh0MV8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGV4dDFCdWlsZGVyXzsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZXh0Ml8gPQogICAgICAgICAgamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVFeHQySXNNdXRhYmxlKCkgewogICAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgICAgICBleHQyXyA9IG5ldyBqYXZhLnV0aWwuQXJyYXlMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+KGV4dDJfKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IGV4dDJCdWlsZGVyXzsKCiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZ2V0RXh0Mkxpc3QoKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGV4dDJfKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBleHQyQnVpbGRlcl8uZ2V0TWVzc2FnZUxpc3QoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgaW50IGdldEV4dDJDb3VudCgpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZXh0Ml8uc2l6ZSgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDJCdWlsZGVyXy5nZXRDb3VudCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEV4dDIoaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDJfLmdldChpbmRleCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZXh0MkJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEV4dDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKGV4dDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlRXh0MklzTXV0YWJsZSgpOwogICAgICAgICAgICBleHQyXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQyQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RXh0MigKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRXh0MklzTXV0YWJsZSgpOwogICAgICAgICAgICBleHQyXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQyQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRXh0Mihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDJfLmFkZCh2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLmFkZE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRXh0MigKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDJfLmFkZChpbmRleCwgdmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRFeHQyKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRXh0MklzTXV0YWJsZSgpOwogICAgICAgICAgICBleHQyXy5hZGQoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5hZGRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEV4dDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGV4dDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUV4dDJJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0Ml8uYWRkKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbEV4dDIoCiAgICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRXh0MklzTXV0YWJsZSgpOwogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgICAgICB2YWx1ZXMsIGV4dDJfKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQyQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRXh0MigpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBleHQyXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwNDApOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlRXh0MihpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldEV4dDJCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIHJldHVybiBnZXRFeHQyRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RXh0Mk9yQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDJfLmdldChpbmRleCk7ICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZXh0MkJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRFeHQyT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZXh0MkJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZXh0Ml8pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYWRkRXh0MkJ1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0RXh0MkZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRFeHQyQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0RXh0MkZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXI+IAogICAgICAgICAgICAgZ2V0RXh0MkJ1aWxkZXJMaXN0KCkgewogICAgICAgICAgcmV0dXJuIGdldEV4dDJGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyTGlzdCgpOwogICAgICAgIH0KICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgZ2V0RXh0MkZpZWxkQnVpbGRlcigpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBleHQyQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgICBleHQyXywKICAgICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgIGV4dDJfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBleHQyQnVpbGRlcl87CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKQogICAgICB9CgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBERUZBVUxUX0lOU1RBTkNFOwogICAgICBzdGF0aWMgewogICAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yPgogICAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3I+KCkgewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEZpZWxkc0dlbmVyYXRvcj4gcGFyc2VyKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICB9CgogICAgcHVibGljIGludGVyZmFjZSBPcHRpb25hbEdyb3VwT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfZ3JvdXBfYWxsX3R5cGVzID0gMTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsR3JvdXBBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBib29sZWFuIGhhc09wdGlvbmFsR3JvdXBBbGxUeXBlcygpOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxHcm91cEFsbFR5cGVzLgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc09yQnVpbGRlcigpOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cH0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBPcHRpb25hbEdyb3VwIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgICBPcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgICAvLyBVc2UgT3B0aW9uYWxHcm91cC5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgICBwcml2YXRlIE9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBPcHRpb25hbEdyb3VwKCkgewogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICByZXR1cm4gbmV3IE9wdGlvbmFsR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX09wdGlvbmFsR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfR1JPVVBfQUxMX1RZUEVTX0ZJRUxEX05VTUJFUiA9IDExOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxHcm91cEFsbFR5cGVzXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxHcm91cEFsbFR5cGVzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxHcm91cEFsbFR5cGVzLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwQWxsVHlwZXNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfZ3JvdXBfYWxsX3R5cGVzID0gMTE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwQWxsVHlwZXNfOwogICAgICB9CgogICAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxMSwgZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpOwogICAgICAgIH0KICAgICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgICBzaXplID0gMDsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDExLCBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgICByZXR1cm4gc2l6ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgICAgfQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCkgb2JqOwoKICAgICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpIHJldHVybiBmYWxzZTsKICAgICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpIHsKICAgICAgICAgIGlmICghZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsR3JvdXBBbGxUeXBlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgICAgfQogICAgICAgIGludCBoYXNoID0gNDE7CiAgICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXBBbGxUeXBlcygpKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9HUk9VUF9BTExfVFlQRVNfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKCkuaGFzaENvZGUoKTsKICAgICAgICB9CiAgICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgICAgcmV0dXJuIGhhc2g7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwcm90b3R5cGUpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICAgIHJldHVybiBidWlsZGVyOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cH0KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9PcHRpb25hbEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgIH0KCiAgICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAubmV3QnVpbGRlcigpCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewogICAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgICBpZiAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAgICAgLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPSBudWxsOwogICAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgb3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBidWlsZCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCh0aGlzKTsKICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCByZXN1bHQpIHsKICAgICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPSBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgICA/IG9wdGlvbmFsR3JvdXBBbGxUeXBlc18KICAgICAgICAgICAgICAgIDogb3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApIHsKICAgICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cClvdGhlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpIHsKICAgICAgICAgICAgbWVyZ2VPcHRpb25hbEdyb3VwQWxsVHlwZXMob3RoZXIuZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA5MDogewogICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSA5MAogICAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsR3JvdXBBbGxUeXBlc187CiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfOwogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEdyb3VwQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsR3JvdXBBbGxUeXBlcygpIHsKICAgICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEdyb3VwQWxsVHlwZXMuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKCkgewogICAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwQWxsVHlwZXNfOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNfID0gdmFsdWU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAob3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VPcHRpb25hbEdyb3VwQWxsVHlwZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApICYmCiAgICAgICAgICAgICAgb3B0aW9uYWxHcm91cEFsbFR5cGVzXyAhPSBudWxsICYmCiAgICAgICAgICAgICAgb3B0aW9uYWxHcm91cEFsbFR5cGVzXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgb3B0aW9uYWxHcm91cEFsbFR5cGVzXyA9IHZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gIT0gbnVsbCkgewogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSB7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICAgIGlmIChvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgb3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXIoKSB7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzT3JCdWlsZGVyKCkgewogICAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQWxsVHlwZXNfID09IG51bGwgPwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBBbGxUeXBlc187CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgICBpZiAob3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSwKICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCgogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwKQogICAgICB9CgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgREVGQVVMVF9JTlNUQU5DRTsKICAgICAgc3RhdGljIHsKICAgICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cD4KICAgICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPE9wdGlvbmFsR3JvdXA+KCkgewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgT3B0aW9uYWxHcm91cCBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE9wdGlvbmFsR3JvdXA+IHBhcnNlcigpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxPcHRpb25hbEdyb3VwPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgIH0KCiAgICBwdWJsaWMgaW50ZXJmYWNlIFJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgcmVwZWF0ZWRHcm91cEFsbFR5cGVzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIGJvb2xlYW4gaGFzUmVwZWF0ZWRHcm91cEFsbFR5cGVzKCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEdyb3VwQWxsVHlwZXMuCiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygpOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzT3JCdWlsZGVyKCk7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFJlcGVhdGVkR3JvdXAgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKQogICAgICAgIFJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAgIC8vIFVzZSBSZXBlYXRlZEdyb3VwLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgIHByaXZhdGUgUmVwZWF0ZWRHcm91cChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgfQogICAgICBwcml2YXRlIFJlcGVhdGVkR3JvdXAoKSB7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICAgIHJldHVybiBuZXcgUmVwZWF0ZWRHcm91cCgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRHcm91cF9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9HUk9VUF9BTExfVFlQRVNfRklFTERfTlVNQkVSID0gMjE7CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZEdyb3VwQWxsVHlwZXNfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSByZXBlYXRlZEdyb3VwQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEdyb3VwQWxsVHlwZXMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlcGVhdGVkR3JvdXBBbGxUeXBlc187CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlc09yQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlcGVhdGVkR3JvdXBBbGxUeXBlc187CiAgICAgIH0KCiAgICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDIxLCBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSk7CiAgICAgICAgfQogICAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICAgIHNpemUgPSAwOwogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMjEsIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICAgIHJldHVybiBzaXplOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgICB9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKSBvYmo7CgogICAgICAgIGlmIChoYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSAhPSBvdGhlci5oYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChoYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSkgewogICAgICAgICAgaWYgKCFnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKQogICAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgICB9CiAgICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgICBpZiAoaGFzUmVwZWF0ZWRHcm91cEFsbFR5cGVzKCkpIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0dST1VQX0FMTF9UWVBFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKS5oYXNoQ29kZSgpOwogICAgICAgIH0KICAgICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgICByZXR1cm4gaGFzaDsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHByb3RvdHlwZSkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgewogICAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cC5uZXdCdWlsZGVyKCkKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgICBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCk7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBzdXBlcihwYXJlbnQpOwogICAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICAgIH0KICAgICAgICBwcml2YXRlIHZvaWQgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpIHsKICAgICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgICAuYWx3YXlzVXNlRmllbGRCdWlsZGVycykgewogICAgICAgICAgICBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9IG51bGw7CiAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIGJ1aWxkKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKHRoaXMpOwogICAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICAgIG9uQnVpbHQoKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHJlc3VsdCkgewogICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICByZXN1bHQucmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9IHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICAgID8gcmVwZWF0ZWRHcm91cEFsbFR5cGVzXwogICAgICAgICAgICAgICAgOiByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkgewogICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKW90aGVyKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICAgIGlmIChvdGhlci5oYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSkgewogICAgICAgICAgICBtZXJnZVJlcGVhdGVkR3JvdXBBbGxUeXBlcyhvdGhlci5nZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDE3MDogewogICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxNzAKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZEdyb3VwQWxsVHlwZXNfOwogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXzsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgcmVwZWF0ZWRHcm91cEFsbFR5cGVzIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgYm9vbGVhbiBoYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSB7CiAgICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRHcm91cEFsbFR5cGVzLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQWxsVHlwZXNfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVwZWF0ZWRHcm91cEFsbFR5cGVzXzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9IHZhbHVlOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlUmVwZWF0ZWRHcm91cEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSAmJgogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBBbGxUeXBlc18gIT0gbnVsbCAmJgogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBBbGxUeXBlc18gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBBbGxUeXBlc18gPSB2YWx1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQWxsVHlwZXNfICE9IG51bGwpIHsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRHcm91cEFsbFR5cGVzKCkgewogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9IG51bGw7CiAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyKCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlc09yQnVpbGRlcigpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9PSBudWxsID8KICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiByZXBlYXRlZEdyb3VwQWxsVHlwZXNfOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzRmllbGRCdWlsZGVyKCkgewogICAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzKCksCiAgICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXzsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgoKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgfQoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIHN0YXRpYyB7CiAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlcGVhdGVkR3JvdXA+CiAgICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxSZXBlYXRlZEdyb3VwPigpIHsKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIFJlcGVhdGVkR3JvdXAgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEdyb3VwPiBwYXJzZXIoKSB7CiAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UmVwZWF0ZWRHcm91cD4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUVVJUkVEX0FMTF9UWVBFU19GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkQWxsVHlwZXNfOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIHJlcXVpcmVkQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNSZXF1aXJlZEFsbFR5cGVzKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIHJlcXVpcmVkQWxsVHlwZXMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldFJlcXVpcmVkQWxsVHlwZXMoKSB7CiAgICAgIHJldHVybiByZXF1aXJlZEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlcXVpcmVkQWxsVHlwZXNfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldFJlcXVpcmVkQWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiByZXF1aXJlZEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlcXVpcmVkQWxsVHlwZXNfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0FMTF9UWVBFU19GSUVMRF9OVU1CRVIgPSAyOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsQWxsVHlwZXNfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEFsbFR5cGVzKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQWxsVHlwZXMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE9wdGlvbmFsQWxsVHlwZXMoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsQWxsVHlwZXNfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsQWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsQWxsVHlwZXNfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0FMTF9UWVBFU19GSUVMRF9OVU1CRVIgPSAzOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IHJlcGVhdGVkQWxsVHlwZXNfOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRSZXBlYXRlZEFsbFR5cGVzTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkQWxsVHlwZXNfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRBbGxUeXBlc09yQnVpbGRlckxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEFsbFR5cGVzXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkQWxsVHlwZXNDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkQWxsVHlwZXNfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRSZXBlYXRlZEFsbFR5cGVzKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc18uZ2V0KGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEFsbFR5cGVzT3JCdWlsZGVyKAogICAgICAgIGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc18uZ2V0KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTEdST1VQX0ZJRUxEX05VTUJFUiA9IDEwOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIG9wdGlvbmFsR3JvdXBfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxncm91cCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsR3JvdXAoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbGdyb3VwLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxHcm91cF8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVER1JPVVBfRklFTERfTlVNQkVSID0gMjA7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cD4gcmVwZWF0ZWRHcm91cF87CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cD4gZ2V0UmVwZWF0ZWRHcm91cExpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cE9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cE9yQnVpbGRlckxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRHcm91cENvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgZ2V0UmVwZWF0ZWRHcm91cChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cE9yQnVpbGRlciBnZXRSZXBlYXRlZEdyb3VwT3JCdWlsZGVyKAogICAgICAgIGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF8uZ2V0KGluZGV4KTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBpZiAoIWhhc1JlcXVpcmVkQWxsVHlwZXMoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZXh0ZW5zaW9uc0FyZUluaXRpYWxpemVkKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLkV4dGVuZGFibGVNZXNzYWdlPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlPi5FeHRlbnNpb25Xcml0ZXIKICAgICAgICAgIGV4dGVuc2lvbldyaXRlciA9IG5ld0V4dGVuc2lvbldyaXRlcigpOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDEsIGdldFJlcXVpcmVkQWxsVHlwZXMoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgyLCBnZXRPcHRpb25hbEFsbFR5cGVzKCkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRBbGxUeXBlc18uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDMsIHJlcGVhdGVkQWxsVHlwZXNfLmdldChpKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlR3JvdXAoMTAsIGdldE9wdGlvbmFsR3JvdXAoKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEdyb3VwXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUdyb3VwKDIwLCByZXBlYXRlZEdyb3VwXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGV4dGVuc2lvbldyaXRlci53cml0ZVVudGlsKDUzNjg3MDkxMiwgb3V0cHV0KTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxLCBnZXRSZXF1aXJlZEFsbFR5cGVzKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyLCBnZXRPcHRpb25hbEFsbFR5cGVzKCkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRBbGxUeXBlc18uc2l6ZSgpOyBpKyspIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMywgcmVwZWF0ZWRBbGxUeXBlc18uZ2V0KGkpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlR3JvdXBTaXplKDEwLCBnZXRPcHRpb25hbEdyb3VwKCkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRHcm91cF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlR3JvdXBTaXplKDIwLCByZXBlYXRlZEdyb3VwXy5nZXQoaSkpOwogICAgICB9CiAgICAgIHNpemUgKz0gZXh0ZW5zaW9uc1NlcmlhbGl6ZWRTaXplKCk7CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc1JlcXVpcmVkQWxsVHlwZXMoKSAhPSBvdGhlci5oYXNSZXF1aXJlZEFsbFR5cGVzKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc1JlcXVpcmVkQWxsVHlwZXMoKSkgewogICAgICAgIGlmICghZ2V0UmVxdWlyZWRBbGxUeXBlcygpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVxdWlyZWRBbGxUeXBlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEFsbFR5cGVzKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxBbGxUeXBlcygpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEFsbFR5cGVzKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsQWxsVHlwZXMoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsQWxsVHlwZXMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFJlcGVhdGVkQWxsVHlwZXNMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRBbGxUeXBlc0xpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSAhPSBvdGhlci5oYXNPcHRpb25hbEdyb3VwKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxHcm91cCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxHcm91cCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRHcm91cExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEdyb3VwTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldEV4dGVuc2lvbkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRFeHRlbnNpb25GaWVsZHMoKSkpCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNSZXF1aXJlZEFsbFR5cGVzKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVFVSVJFRF9BTExfVFlQRVNfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcXVpcmVkQWxsVHlwZXMoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEFsbFR5cGVzKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9BTExfVFlQRVNfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsQWxsVHlwZXMoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEFsbFR5cGVzQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9BTExfVFlQRVNfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkQWxsVHlwZXNMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxHUk9VUF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxHcm91cCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGdldFJlcGVhdGVkR3JvdXBDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVER1JPVVBfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkR3JvdXBMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gaGFzaEZpZWxkcyhoYXNoLCBnZXRFeHRlbnNpb25GaWVsZHMoKSk7CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBTZWUgdGhlIGNvbW1lbnRzIG9mIHRoZSBzYW1lIHR5cGUgaW4gdW5pdHRlc3QucHJvdG8uCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSwgQnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewogICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwogICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpIHsKICAgICAgICBpZiAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICBnZXRSZXF1aXJlZEFsbFR5cGVzRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRPcHRpb25hbEFsbFR5cGVzRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRSZXBlYXRlZEFsbFR5cGVzRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRSZXBlYXRlZEdyb3VwRmllbGRCdWlsZGVyKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICByZXF1aXJlZEFsbFR5cGVzXyA9IG51bGw7CiAgICAgICAgaWYgKHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3B0aW9uYWxBbGxUeXBlc18gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGlmIChyZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgb3B0aW9uYWxHcm91cF8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfID0gbnVsbDsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSh0aGlzKTsKICAgICAgICBidWlsZFBhcnRpYWxSZXBlYXRlZEZpZWxkcyhyZXN1bHQpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWxSZXBlYXRlZEZpZWxkcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSByZXN1bHQpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkQWxsVHlwZXNfKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkQWxsVHlwZXNfID0gcmVwZWF0ZWRBbGxUeXBlc187CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEFsbFR5cGVzXyA9IHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkR3JvdXBfID0gcmVwZWF0ZWRHcm91cF87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEdyb3VwXyA9IHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQucmVxdWlyZWRBbGxUeXBlc18gPSByZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gcmVxdWlyZWRBbGxUeXBlc18KICAgICAgICAgICAgICA6IHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsQWxsVHlwZXNfID0gb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsQWxsVHlwZXNfCiAgICAgICAgICAgICAgOiBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEdyb3VwXyA9IG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgPyBvcHRpb25hbEdyb3VwXwogICAgICAgICAgICAgIDogb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLCBUeXBlPiBleHRlbnNpb24sCiAgICAgICAgICBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgaW50IGluZGV4LCBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgYWRkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkRXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUPiBCdWlsZGVyIGNsZWFyRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSwgVD4gZXh0ZW5zaW9uKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRXh0ZW5zaW9uKGV4dGVuc2lvbik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzUmVxdWlyZWRBbGxUeXBlcygpKSB7CiAgICAgICAgICBtZXJnZVJlcXVpcmVkQWxsVHlwZXMob3RoZXIuZ2V0UmVxdWlyZWRBbGxUeXBlcygpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsQWxsVHlwZXMoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbEFsbFR5cGVzKG90aGVyLmdldE9wdGlvbmFsQWxsVHlwZXMoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChyZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEFsbFR5cGVzXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNfID0gb3RoZXIucmVwZWF0ZWRBbGxUeXBlc187CiAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKTsKICAgICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRBbGxUeXBlc18pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkQWxsVHlwZXNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXyA9IG90aGVyLnJlcGVhdGVkQWxsVHlwZXNfOwogICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMgPwogICAgICAgICAgICAgICAgICAgZ2V0UmVwZWF0ZWRBbGxUeXBlc0ZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIucmVwZWF0ZWRBbGxUeXBlc18pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEdyb3VwKCkpIHsKICAgICAgICAgIG1lcmdlT3B0aW9uYWxHcm91cChvdGhlci5nZXRPcHRpb25hbEdyb3VwKCkpOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRHcm91cF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IG90aGVyLnJlcGVhdGVkR3JvdXBfOwogICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8uYWRkQWxsKG90aGVyLnJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEdyb3VwXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBvdGhlci5yZXBlYXRlZEdyb3VwXzsKICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLnJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlRXh0ZW5zaW9uRmllbGRzKG90aGVyKTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFoYXNSZXF1aXJlZEFsbFR5cGVzKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTA6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldFJlcXVpcmVkQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEwCiAgICAgICAgICAgICAgY2FzZSAxODogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTgKICAgICAgICAgICAgICBjYXNlIDI2OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlBBUlNFUiwKICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18uYWRkKG0pOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmFkZE1lc3NhZ2UobSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjYKICAgICAgICAgICAgICBjYXNlIDgzOiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoMTAsCiAgICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODMKICAgICAgICAgICAgICBjYXNlIDE2MzogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBtID0KICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoMjAsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwXy5hZGQobSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uYWRkTWVzc2FnZShtKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjMKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkQWxsVHlwZXNfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSByZXF1aXJlZEFsbFR5cGVzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc1JlcXVpcmVkQWxsVHlwZXMoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIHJlcXVpcmVkQWxsVHlwZXMuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRSZXF1aXJlZEFsbFR5cGVzKCkgewogICAgICAgIGlmIChyZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcXVpcmVkQWxsVHlwZXNfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVxdWlyZWRBbGxUeXBlc187CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkX2FsbF90eXBlcyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVxdWlyZWRBbGxUeXBlcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNfID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXF1aXJlZEFsbFR5cGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc18gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlUmVxdWlyZWRBbGxUeXBlcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkgJiYKICAgICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc18gIT0gbnVsbCAmJgogICAgICAgICAgICByZXF1aXJlZEFsbFR5cGVzXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgIGdldFJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgIH0KICAgICAgICBpZiAocmVxdWlyZWRBbGxUeXBlc18gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcXVpcmVkQWxsVHlwZXMoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIHJlcXVpcmVkQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICBpZiAocmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICByZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkX2FsbF90eXBlcyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRSZXF1aXJlZEFsbFR5cGVzQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldFJlcXVpcmVkQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldFJlcXVpcmVkQWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcXVpcmVkQWxsVHlwZXNfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiByZXF1aXJlZEFsbFR5cGVzXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRSZXF1aXJlZEFsbFR5cGVzRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChyZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgZ2V0UmVxdWlyZWRBbGxUeXBlcygpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc18gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxBbGxUeXBlc187CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxBbGxUeXBlcygpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxBbGxUeXBlcy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE9wdGlvbmFsQWxsVHlwZXMoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxBbGxUeXBlc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEFsbFR5cGVzXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc18gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsQWxsVHlwZXMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VPcHRpb25hbEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzXyAhPSBudWxsICYmCiAgICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxBbGxUeXBlc0J1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc18gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbEFsbFR5cGVzXyAhPSBudWxsKSB7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxBbGxUeXBlcygpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgb3B0aW9uYWxBbGxUeXBlc18gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldE9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gZ2V0T3B0aW9uYWxBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxBbGxUeXBlc09yQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxBbGxUeXBlc18gPT0gbnVsbCA/CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsQWxsVHlwZXNfOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEFsbFR5cGVzKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gcmVwZWF0ZWRBbGxUeXBlc18gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18gPSBuZXcgamF2YS51dGlsLkFycmF5TGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPihyZXBlYXRlZEFsbFR5cGVzXyk7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgIH0KICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXzsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZ2V0UmVwZWF0ZWRBbGxUeXBlc0xpc3QoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRBbGxUeXBlc18pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkQWxsVHlwZXNDb3VudCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEFsbFR5cGVzXy5zaXplKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uZ2V0Q291bnQoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldFJlcGVhdGVkQWxsVHlwZXMoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc18uZ2V0KGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkQWxsVHlwZXMoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRBbGxUeXBlc0lzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkQWxsVHlwZXMoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRBbGxUeXBlc0lzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18uYWRkKHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uYWRkTWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEFsbFR5cGVzKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNfLmFkZChpbmRleCwgdmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEFsbFR5cGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRBbGxUeXBlc0lzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uYWRkTWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEFsbFR5cGVzKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEFsbFR5cGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRBbGxUeXBlcygKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEFsbFR5cGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZEFsbFR5cGVzXyk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKHZhbHVlcyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkQWxsVHlwZXMoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVJlcGVhdGVkQWxsVHlwZXMoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEFsbFR5cGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5yZW1vdmUoaW5kZXgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRSZXBlYXRlZEFsbFR5cGVzQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEFsbFR5cGVzRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkQWxsVHlwZXNPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEFsbFR5cGVzXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcihpbmRleCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgIGdldFJlcGVhdGVkQWxsVHlwZXNPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRBbGxUeXBlc18pOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRSZXBlYXRlZEFsbFR5cGVzQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGFkZFJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXI+IAogICAgICAgICAgIGdldFJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXJMaXN0KCk7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0UmVwZWF0ZWRBbGxUeXBlc0ZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18sCiAgICAgICAgICAgICAgICAgICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgb3B0aW9uYWxHcm91cF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlcj4gb3B0aW9uYWxHcm91cEJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxncm91cCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEdyb3VwKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsZ3JvdXAuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxHcm91cF87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEdyb3VwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxHcm91cCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxHcm91cChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkgJiYKICAgICAgICAgICAgb3B0aW9uYWxHcm91cF8gIT0gbnVsbCAmJgogICAgICAgICAgICBvcHRpb25hbEdyb3VwXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgIH0KICAgICAgICBpZiAob3B0aW9uYWxHcm91cF8gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxHcm91cCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwOCk7CiAgICAgICAgb3B0aW9uYWxHcm91cF8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIgZ2V0T3B0aW9uYWxHcm91cEJ1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRPcHRpb25hbEdyb3VwRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvcHRpb25hbEdyb3VwXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cD4gcmVwZWF0ZWRHcm91cF8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkR3JvdXBJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBuZXcgamF2YS51dGlsLkFycmF5TGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwPihyZXBlYXRlZEdyb3VwXyk7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgIH0KICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXI+IHJlcGVhdGVkR3JvdXBCdWlsZGVyXzsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwPiBnZXRSZXBlYXRlZEdyb3VwTGlzdCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZEdyb3VwXyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQnVpbGRlcl8uZ2V0TWVzc2FnZUxpc3QoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEdyb3VwQ291bnQoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF8uc2l6ZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIGdldFJlcGVhdGVkR3JvdXAoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF8uZ2V0KGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5nZXRNZXNzYWdlKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRHcm91cCgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEdyb3VwKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEdyb3VwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cF8uYWRkKHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uYWRkTWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkR3JvdXAoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cF8uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRHcm91cCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkR3JvdXBJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmFkZE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEdyb3VwKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEdyb3VwKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwPiB2YWx1ZXMpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkR3JvdXBJc011dGFibGUoKTsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEdyb3VwKCkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVJlcGVhdGVkR3JvdXAoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5yZW1vdmUoaW5kZXgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cC5CdWlsZGVyIGdldFJlcGVhdGVkR3JvdXBCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkR3JvdXBGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cE9yQnVpbGRlciBnZXRSZXBlYXRlZEdyb3VwT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF8uZ2V0KGluZGV4KTsgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXI+IAogICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRHcm91cF8pOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cC5CdWlsZGVyIGFkZFJlcGVhdGVkR3JvdXBCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEdyb3VwRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlciBhZGRSZXBlYXRlZEdyb3VwQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEdyb3VwRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXI+IAogICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRHcm91cEZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXJMaXN0KCk7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cEZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cC5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8sCiAgICAgICAgICAgICAgICAgICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEJ1aWxkZXJfOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdFBhcnNpbmdNZXJnZUxpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdFBhcnNpbmdNZXJnZUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0UGFyc2luZ01lcmdlTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RQYXJzaW5nTWVyZ2VMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RQYXJzaW5nTWVyZ2VMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9FWFRfRklFTERfTlVNQkVSID0gMTAwMDsKICAgIC8qKgogICAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IG9wdGlvbmFsRXh0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAgIC5uZXdNZXNzYWdlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCksCiAgICAgICAgICAwLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5jbGFzcywKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRVhUX0ZJRUxEX05VTUJFUiA9IDEwMDE7CiAgICAvKioKICAgICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSwKICAgICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPj4gcmVwZWF0ZWRFeHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgICAgLm5ld01lc3NhZ2VTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSwKICAgICAgICAgIDEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmNsYXNzLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhbGxFeHRlbnNpb25zIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNBbGxFeHRlbnNpb25zKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhbGxFeHRlbnNpb25zLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgZ2V0QWxsRXh0ZW5zaW9ucygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXIgZ2V0QWxsRXh0ZW5zaW9uc09yQnVpbGRlcigpOwogIH0KICAvKioKICAgKiA8cHJlPgogICAqIFRlc3QgdGhhdCB0aGUgY29ycmVjdCBleGNlcHRpb24gaXMgdGhyb3duIGJ5IHBhcnNlRnJvbSBpbiBhIGNvcm5lciBjYXNlCiAgICogaW52b2x2aW5nIG1lcmdpbmcsIGV4dGVuc2lvbnMsIGFuZCByZXF1aXJlZCBmaWVsZHMuCiAgICogPC9wcmU+CiAgICoKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUpCiAgICAgIFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEFMTF9FWFRFTlNJT05TX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxFeHRlbnNpb25zXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYWxsRXh0ZW5zaW9ucyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0FsbEV4dGVuc2lvbnMoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGFsbEV4dGVuc2lvbnMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgZ2V0QWxsRXh0ZW5zaW9ucygpIHsKICAgICAgcmV0dXJuIGFsbEV4dGVuc2lvbnNfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBhbGxFeHRlbnNpb25zXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciBnZXRBbGxFeHRlbnNpb25zT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gYWxsRXh0ZW5zaW9uc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGFsbEV4dGVuc2lvbnNfOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkpIHsKICAgICAgICBpZiAoIWdldEFsbEV4dGVuc2lvbnMoKS5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxLCBnZXRBbGxFeHRlbnNpb25zKCkpOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMSwgZ2V0QWxsRXh0ZW5zaW9ucygpKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUpIG9iajsKCiAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkgIT0gb3RoZXIuaGFzQWxsRXh0ZW5zaW9ucygpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkpIHsKICAgICAgICBpZiAoIWdldEFsbEV4dGVuc2lvbnMoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldEFsbEV4dGVuc2lvbnMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBBTExfRVhURU5TSU9OU19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0QWxsRXh0ZW5zaW9ucygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogVGVzdCB0aGF0IHRoZSBjb3JyZWN0IGV4Y2VwdGlvbiBpcyB0aHJvd24gYnkgcGFyc2VGcm9tIGluIGEgY29ybmVyIGNhc2UKICAgICAqIGludm9sdmluZyBtZXJnaW5nLCBleHRlbnNpb25zLCBhbmQgcmVxdWlyZWQgZmllbGRzLgogICAgICogPC9wcmU+CiAgICAgKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXJnZUV4Y2VwdGlvbkxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKICAgICAgICBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCk7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgaWYgKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgICAuYWx3YXlzVXNlRmllbGRCdWlsZGVycykgewogICAgICAgICAgZ2V0QWxsRXh0ZW5zaW9uc0ZpZWxkQnVpbGRlcigpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgYWxsRXh0ZW5zaW9uc18gPSBudWxsOwogICAgICAgIGlmIChhbGxFeHRlbnNpb25zQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgYWxsRXh0ZW5zaW9uc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXJnZUV4Y2VwdGlvbkxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuYWxsRXh0ZW5zaW9uc18gPSBhbGxFeHRlbnNpb25zQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gYWxsRXh0ZW5zaW9uc18KICAgICAgICAgICAgICA6IGFsbEV4dGVuc2lvbnNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNBbGxFeHRlbnNpb25zKCkpIHsKICAgICAgICAgIG1lcmdlQWxsRXh0ZW5zaW9ucyhvdGhlci5nZXRBbGxFeHRlbnNpb25zKCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKGhhc0FsbEV4dGVuc2lvbnMoKSkgewogICAgICAgICAgaWYgKCFnZXRBbGxFeHRlbnNpb25zKCkuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDEwOiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRBbGxFeHRlbnNpb25zRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxFeHRlbnNpb25zXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlT3JCdWlsZGVyPiBhbGxFeHRlbnNpb25zQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGFsbEV4dGVuc2lvbnMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzQWxsRXh0ZW5zaW9ucygpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGFsbEV4dGVuc2lvbnMuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGdldEFsbEV4dGVuc2lvbnMoKSB7CiAgICAgICAgaWYgKGFsbEV4dGVuc2lvbnNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gYWxsRXh0ZW5zaW9uc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGFsbEV4dGVuc2lvbnNfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gYWxsRXh0ZW5zaW9uc0J1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRBbGxFeHRlbnNpb25zKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChhbGxFeHRlbnNpb25zQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBhbGxFeHRlbnNpb25zXyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhbGxFeHRlbnNpb25zQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEFsbEV4dGVuc2lvbnMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAoYWxsRXh0ZW5zaW9uc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VBbGxFeHRlbnNpb25zKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChhbGxFeHRlbnNpb25zQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApICYmCiAgICAgICAgICAgIGFsbEV4dGVuc2lvbnNfICE9IG51bGwgJiYKICAgICAgICAgICAgYWxsRXh0ZW5zaW9uc18gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgIGdldEFsbEV4dGVuc2lvbnNCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGFsbEV4dGVuc2lvbnNfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgIH0KICAgICAgICBpZiAoYWxsRXh0ZW5zaW9uc18gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJBbGxFeHRlbnNpb25zKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBhbGxFeHRlbnNpb25zXyA9IG51bGw7CiAgICAgICAgaWYgKGFsbEV4dGVuc2lvbnNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBhbGxFeHRlbnNpb25zQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgYWxsRXh0ZW5zaW9uc0J1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLkJ1aWxkZXIgZ2V0QWxsRXh0ZW5zaW9uc0J1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRBbGxFeHRlbnNpb25zRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciBnZXRBbGxFeHRlbnNpb25zT3JCdWlsZGVyKCkgewogICAgICAgIGlmIChhbGxFeHRlbnNpb25zQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGFsbEV4dGVuc2lvbnNCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBhbGxFeHRlbnNpb25zXyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBhbGxFeHRlbnNpb25zXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0QWxsRXh0ZW5zaW9uc0ZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAoYWxsRXh0ZW5zaW9uc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIGdldEFsbEV4dGVuc2lvbnMoKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGFsbEV4dGVuc2lvbnNCdWlsZGVyXzsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWVyZ2VFeGNlcHRpb25MaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0TWVyZ2VFeGNlcHRpb25MaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE1lcmdlRXhjZXB0aW9uTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWVyZ2VFeGNlcHRpb25MaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdEVtcHR5TWVzc2FnZUxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RFbXB0eU1lc3NhZ2VMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewogIH0KICAvKioKICAgKiA8cHJlPgogICAqIFRlc3RFbXB0eU1lc3NhZ2VMaXRlIGlzIHVzZWQgdG8gdGVzdCB1bmtub3duIGZpZWxkcyBzdXBwb3J0IGluIGxpdGUgbW9kZS4KICAgKiA8L3ByZT4KICAgKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RFbXB0eU1lc3NhZ2VMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlTGl0ZSkKICAgICAgVGVzdEVtcHR5TWVzc2FnZUxpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RFbXB0eU1lc3NhZ2VMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RFbXB0eU1lc3NhZ2VMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdEVtcHR5TWVzc2FnZUxpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdEVtcHR5TWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUpIG9iajsKCiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRlc3RFbXB0eU1lc3NhZ2VMaXRlIGlzIHVzZWQgdG8gdGVzdCB1bmtub3duIGZpZWxkcyBzdXBwb3J0IGluIGxpdGUgbW9kZS4KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUodGhpcyk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RFbXB0eU1lc3NhZ2VMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVtcHR5TWVzc2FnZUxpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdEVtcHR5TWVzc2FnZUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0RW1wdHlNZXNzYWdlTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbXB0eU1lc3NhZ2VMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbXB0eU1lc3NhZ2VMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLgogICAgICAgICAgRXh0ZW5kYWJsZU1lc3NhZ2VPckJ1aWxkZXI8VGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZT4gewogIH0KICAvKioKICAgKiA8cHJlPgogICAqIExpa2UgYWJvdmUsIGJ1dCBkZWNsYXJlIGFsbCBmaWVsZCBudW1iZXJzIGFzIHBvdGVudGlhbCBleHRlbnNpb25zLiAgTm8KICAgKiBhY3R1YWwgZXh0ZW5zaW9ucyBzaG91bGQgZXZlciBiZSBkZWZpbmVkIGZvciB0aGlzIHR5cGUuCiAgICogPC9wcmU+CiAgICoKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlTWVzc2FnZTwKICAgICAgICBUZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlPiBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUpCiAgICAgIFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlQnVpbGRlcjxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLCA/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmICghZXh0ZW5zaW9uc0FyZUluaXRpYWxpemVkKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLkV4dGVuZGFibGVNZXNzYWdlPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGU+LkV4dGVuc2lvbldyaXRlcgogICAgICAgICAgZXh0ZW5zaW9uV3JpdGVyID0gbmV3RXh0ZW5zaW9uV3JpdGVyKCk7CiAgICAgIGV4dGVuc2lvbldyaXRlci53cml0ZVVudGlsKDUzNjg3MDkxMiwgb3V0cHV0KTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHNpemUgKz0gZXh0ZW5zaW9uc1NlcmlhbGl6ZWRTaXplKCk7CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRFeHRlbnNpb25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0RXh0ZW5zaW9uRmllbGRzKCkpKQogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBoYXNoID0gaGFzaEZpZWxkcyhoYXNoLCBnZXRFeHRlbnNpb25GaWVsZHMoKSk7CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIExpa2UgYWJvdmUsIGJ1dCBkZWNsYXJlIGFsbCBmaWVsZCBudW1iZXJzIGFzIHBvdGVudGlhbCBleHRlbnNpb25zLiAgTm8KICAgICAqIGFjdHVhbCBleHRlbnNpb25zIHNob3VsZCBldmVyIGJlIGRlZmluZWQgZm9yIHRoaXMgdHlwZS4KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSwgQnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSh0aGlzKTsKICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIHNldEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSwgVHlwZT4gZXh0ZW5zaW9uLAogICAgICAgICAgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRFeHRlbnNpb24oZXh0ZW5zaW9uLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgc2V0RXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgaW50IGluZGV4LCBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgYWRkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRFeHRlbnNpb24oZXh0ZW5zaW9uLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFQ+IEJ1aWxkZXIgY2xlYXJFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUsIFQ+IGV4dGVuc2lvbikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckV4dGVuc2lvbihleHRlbnNpb24pOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICB0aGlzLm1lcmdlRXh0ZW5zaW9uRmllbGRzKG90aGVyKTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBWMU1lc3NhZ2VMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5WMU1lc3NhZ2VMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGludEZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNJbnRGaWVsZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBpbnRfZmllbGQgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGludEZpZWxkLgogICAgICovCiAgICBpbnQgZ2V0SW50RmllbGQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVjFFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYxX0ZJUlNUXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGVudW1GaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRW51bUZpZWxkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVjFFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYxX0ZJUlNUXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtRmllbGQuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUgZ2V0RW51bUZpZWxkKCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5WMU1lc3NhZ2VMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVjFNZXNzYWdlTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVjFNZXNzYWdlTGl0ZSkKICAgICAgVjFNZXNzYWdlTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVjFNZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBWMU1lc3NhZ2VMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVjFNZXNzYWdlTGl0ZSgpIHsKICAgICAgZW51bUZpZWxkXyA9IDE7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVjFNZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVjFNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVjFNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IElOVF9GSUVMRF9GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBpbnQgaW50RmllbGRfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGludEZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzSW50RmllbGQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBpbnRGaWVsZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRJbnRGaWVsZCgpIHsKICAgICAgcmV0dXJuIGludEZpZWxkXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFTlVNX0ZJRUxEX0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIGludCBlbnVtRmllbGRfID0gMTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5WMUVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjFfRklSU1RdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZW51bUZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNFbnVtRmllbGQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5WMUVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjFfRklSU1RdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGVudW1GaWVsZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFFbnVtTGl0ZSBnZXRFbnVtRmllbGQoKSB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFFbnVtTGl0ZS5mb3JOdW1iZXIoZW51bUZpZWxkXyk7CiAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUuVjFfRklSU1QgOiByZXN1bHQ7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgaWYgKCFoYXNJbnRGaWVsZCgpKSB7CiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigxLCBpbnRGaWVsZF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oMiwgZW51bUZpZWxkXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMSwgaW50RmllbGRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRW51bVNpemUoMiwgZW51bUZpZWxkXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlKSBvYmo7CgogICAgICBpZiAoaGFzSW50RmllbGQoKSAhPSBvdGhlci5oYXNJbnRGaWVsZCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNJbnRGaWVsZCgpKSB7CiAgICAgICAgaWYgKGdldEludEZpZWxkKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0SW50RmllbGQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNFbnVtRmllbGQoKSAhPSBvdGhlci5oYXNFbnVtRmllbGQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRW51bUZpZWxkKCkpIHsKICAgICAgICBpZiAoZW51bUZpZWxkXyAhPSBvdGhlci5lbnVtRmllbGRfKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoaGFzSW50RmllbGQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIElOVF9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0SW50RmllbGQoKTsKICAgICAgfQogICAgICBpZiAoaGFzRW51bUZpZWxkKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBFTlVNX0ZJRUxEX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBlbnVtRmllbGRfOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlYxTWVzc2FnZUxpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVjFNZXNzYWdlTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVjFNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YxTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGludEZpZWxkXyA9IDA7CiAgICAgICAgZW51bUZpZWxkXyA9IDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVjFNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5pbnRGaWVsZF8gPSBpbnRGaWVsZF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZW51bUZpZWxkXyA9IGVudW1GaWVsZF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKG90aGVyLmhhc0ludEZpZWxkKCkpIHsKICAgICAgICAgIHNldEludEZpZWxkKG90aGVyLmdldEludEZpZWxkKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRW51bUZpZWxkKCkpIHsKICAgICAgICAgIHNldEVudW1GaWVsZChvdGhlci5nZXRFbnVtRmllbGQoKSk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBpZiAoIWhhc0ludEZpZWxkKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIGludEZpZWxkXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgKICAgICAgICAgICAgICBjYXNlIDE2OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUgdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCgyLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZW51bUZpZWxkXyA9IHRtcFJhdzsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IGludEZpZWxkXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBpbnRfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBpbnRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0ludEZpZWxkKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGludEZpZWxkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEludEZpZWxkKCkgewogICAgICAgIHJldHVybiBpbnRGaWVsZF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGludEZpZWxkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0SW50RmllbGQoaW50IHZhbHVlKSB7CgogICAgICAgIGludEZpZWxkXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFySW50RmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGludEZpZWxkXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGVudW1GaWVsZF8gPSAxOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5WMUVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjFfRklSU1RdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBlbnVtRmllbGQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNFbnVtRmllbGQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlYxRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMV9GSVJTVF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtRmllbGQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMUVudW1MaXRlIGdldEVudW1GaWVsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMUVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUuZm9yTnVtYmVyKGVudW1GaWVsZF8pOwogICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUuVjFfRklSU1QgOiByZXN1bHQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVjFFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYxX0ZJUlNUXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZW51bUZpZWxkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RW51bUZpZWxkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBlbnVtRmllbGRfID0gdmFsdWUuZ2V0TnVtYmVyKCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVjFFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYxX0ZJUlNUXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRW51bUZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICBlbnVtRmllbGRfID0gMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVjFNZXNzYWdlTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlYxTWVzc2FnZUxpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxWMU1lc3NhZ2VMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFYxTWVzc2FnZUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBWMU1lc3NhZ2VMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VjFNZXNzYWdlTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxWMU1lc3NhZ2VMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVjJNZXNzYWdlTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuVjJNZXNzYWdlTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBpbnRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzSW50RmllbGQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBpbnRGaWVsZC4KICAgICAqLwogICAgaW50IGdldEludEZpZWxkKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlYyRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMl9GSVJTVF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBlbnVtRmllbGQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0VudW1GaWVsZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlYyRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMl9GSVJTVF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZW51bUZpZWxkLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIGdldEVudW1GaWVsZCgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVjJNZXNzYWdlTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFYyTWVzc2FnZUxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlYyTWVzc2FnZUxpdGUpCiAgICAgIFYyTWVzc2FnZUxpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFYyTWVzc2FnZUxpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVjJNZXNzYWdlTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFYyTWVzc2FnZUxpdGUoKSB7CiAgICAgIGVudW1GaWVsZF8gPSAxOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFYyTWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBJTlRfRklFTERfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgaW50IGludEZpZWxkXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBpbnRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0ludEZpZWxkKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgaW50RmllbGQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0SW50RmllbGQoKSB7CiAgICAgIHJldHVybiBpbnRGaWVsZF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRU5VTV9GSUVMRF9GSUVMRF9OVU1CRVIgPSAyOwogICAgcHJpdmF0ZSBpbnQgZW51bUZpZWxkXyA9IDE7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVjJFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYyX0ZJUlNUXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGVudW1GaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzRW51bUZpZWxkKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVjJFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYyX0ZJUlNUXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtRmllbGQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUgZ2V0RW51bUZpZWxkKCkgewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuZm9yTnVtYmVyKGVudW1GaWVsZF8pOwogICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlLlYyX0ZJUlNUIDogcmVzdWx0OwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmICghaGFzSW50RmllbGQoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMSwgaW50RmllbGRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtKDIsIGVudW1GaWVsZF8pOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDEsIGludEZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUVudW1TaXplKDIsIGVudW1GaWVsZF8pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc0ludEZpZWxkKCkgIT0gb3RoZXIuaGFzSW50RmllbGQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzSW50RmllbGQoKSkgewogICAgICAgIGlmIChnZXRJbnRGaWVsZCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldEludEZpZWxkKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRW51bUZpZWxkKCkgIT0gb3RoZXIuaGFzRW51bUZpZWxkKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0VudW1GaWVsZCgpKSB7CiAgICAgICAgaWYgKGVudW1GaWVsZF8gIT0gb3RoZXIuZW51bUZpZWxkXykgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0ludEZpZWxkKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBJTlRfRklFTERfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEludEZpZWxkKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0VudW1GaWVsZCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgRU5VTV9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZW51bUZpZWxkXzsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5WMk1lc3NhZ2VMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlYyTWVzc2FnZUxpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9WMk1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBpbnRGaWVsZF8gPSAwOwogICAgICAgIGVudW1GaWVsZF8gPSAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuaW50RmllbGRfID0gaW50RmllbGRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmVudW1GaWVsZF8gPSBlbnVtRmllbGRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNJbnRGaWVsZCgpKSB7CiAgICAgICAgICBzZXRJbnRGaWVsZChvdGhlci5nZXRJbnRGaWVsZCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0VudW1GaWVsZCgpKSB7CiAgICAgICAgICBzZXRFbnVtRmllbGQob3RoZXIuZ2V0RW51bUZpZWxkKCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFoYXNJbnRGaWVsZCgpKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICBpbnRGaWVsZF8gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4CiAgICAgICAgICAgICAgY2FzZSAxNjogewogICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoMiwgdG1wUmF3KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGVudW1GaWVsZF8gPSB0bXBSYXc7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNgogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGludCBpbnRGaWVsZF8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgaW50RmllbGQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNJbnRGaWVsZCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBpbnRGaWVsZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRJbnRGaWVsZCgpIHsKICAgICAgICByZXR1cm4gaW50RmllbGRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBpbnRfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBpbnRGaWVsZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEludEZpZWxkKGludCB2YWx1ZSkgewoKICAgICAgICBpbnRGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckludEZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBpbnRGaWVsZF8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBlbnVtRmllbGRfID0gMTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuVjJFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYyX0ZJUlNUXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZW51bUZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzRW51bUZpZWxkKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5WMkVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjJfRklSU1RdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZW51bUZpZWxkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSBnZXRFbnVtRmllbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlLmZvck51bWJlcihlbnVtRmllbGRfKTsKICAgICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlLlYyX0ZJUlNUIDogcmVzdWx0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlYyRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMl9GSVJTVF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGVudW1GaWVsZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEVudW1GaWVsZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgZW51bUZpZWxkXyA9IHZhbHVlLmdldE51bWJlcigpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlYyRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMl9GSVJTVF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckVudW1GaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgZW51bUZpZWxkXyA9IDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlYyTWVzc2FnZUxpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5WMk1lc3NhZ2VMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VjJNZXNzYWdlTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxWMk1lc3NhZ2VMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVjJNZXNzYWdlTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFYyTWVzc2FnZUxpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VjJNZXNzYWdlTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy4KICAgICAgICAgIEV4dGVuZGFibGVNZXNzYWdlT3JCdWlsZGVyPFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZT4gewoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSA1MzY4NzAwMDA7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEludDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gNTM2ODcwMDAwOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW50MzIuCiAgICAgKi8KICAgIGludCBnZXRPcHRpb25hbEludDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBmaXhlZF8zMiA9IDUzNjg3MDAwMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0ZpeGVkMzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZml4ZWRfMzIgPSA1MzY4NzAwMDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZml4ZWQzMi4KICAgICAqLwogICAgaW50IGdldEZpeGVkMzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbnQzMi4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IGdldFJlcGVhdGVkSW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbnQzMi4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkSW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA1MzY4NzAwMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UGFja2VkSW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDUzNjg3MDAwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkSW50MzIuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRJbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDUzNjg3MDAwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRJbnQzMihpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZW51bSA9IDUzNjg3MDAwNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxFbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIG9wdGlvbmFsX2VudW0gPSA1MzY4NzAwMDQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxFbnVtLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgZ2V0T3B0aW9uYWxFbnVtKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gNTM2ODcwMDA1OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTdHJpbmcuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T3B0aW9uYWxTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxTdHJpbmcuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9wdGlvbmFsU3RyaW5nQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIG9wdGlvbmFsX2J5dGVzID0gNTM2ODcwMDA2OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxCeXRlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDUzNjg3MDAwNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEJ5dGVzLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T3B0aW9uYWxCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxNZXNzYWdlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxNZXNzYWdlT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gNTM2ODcwMDA4IHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsZ3JvdXAgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsR3JvdXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDUzNjg3MDAwOCB7IC4uLiB9PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxncm91cC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgZ2V0T3B0aW9uYWxHcm91cCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gNTM2ODcwMDA4IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgc3RyaW5nX3N0cmluZ19tYXAgPSA1MzY4NzAwMTA7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0U3RyaW5nU3RyaW5nTWFwQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBzdHJpbmdfc3RyaW5nX21hcCA9IDUzNjg3MDAxMDs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNTdHJpbmdTdHJpbmdNYXAoCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRTdHJpbmdTdHJpbmdNYXBNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICBnZXRTdHJpbmdTdHJpbmdNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBzdHJpbmdfc3RyaW5nX21hcCA9IDUzNjg3MDAxMDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgIGdldFN0cmluZ1N0cmluZ01hcE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KamF2YS5sYW5nLlN0cmluZyBnZXRTdHJpbmdTdHJpbmdNYXBPckRlZmF1bHQoCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KamF2YS5sYW5nLlN0cmluZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRTdHJpbmdTdHJpbmdNYXBPclRocm93KAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSA1MzY4NzAwMTE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlVpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZVaW50MzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+dWludDMyIG9uZW9mX3VpbnQzMiA9IDUzNjg3MDAxMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlVpbnQzMi4KICAgICAqLwogICAgaW50IGdldE9uZW9mVWludDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlRlc3RBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZUZXN0QWxsVHlwZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mVGVzdEFsbFR5cGVzLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE9uZW9mVGVzdEFsbFR5cGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T25lb2ZUZXN0QWxsVHlwZXNPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSA1MzY4NzAwMTM7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZy4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gNTM2ODcwMDEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA1MzY4NzAwMTQ7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNTM2ODcwMDE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mQnl0ZXMuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPbmVvZkJ5dGVzKCk7CgogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9uZW9mRmllbGRDYXNlIGdldE9uZW9mRmllbGRDYXNlKCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlTWVzc2FnZTwKICAgICAgICBUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGU+IGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKQogICAgICBUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLCA/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUoKSB7CiAgICAgIHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHBhY2tlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBvcHRpb25hbEVudW1fID0gNDsKICAgICAgb3B0aW9uYWxTdHJpbmdfID0gIiI7CiAgICAgIG9wdGlvbmFsQnl0ZXNfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgaW50IG51bWJlcikgewogICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgIGNhc2UgNTM2ODcwMDEwOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICB9CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBpbnRlcmZhY2UgT3B0aW9uYWxHcm91cE9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGdyb3VwX2EgPSA1MzY4NzAwMDk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGdyb3VwQSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBib29sZWFuIGhhc0dyb3VwQSgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZ3JvdXBfYSA9IDUzNjg3MDAwOTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGdyb3VwQS4KICAgICAgICovCiAgICAgIGludCBnZXRHcm91cEEoKTsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIE9wdGlvbmFsR3JvdXAgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgICBPcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgICAvLyBVc2UgT3B0aW9uYWxHcm91cC5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgICBwcml2YXRlIE9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBPcHRpb25hbEdyb3VwKCkgewogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICByZXR1cm4gbmV3IE9wdGlvbmFsR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEdST1VQX0FfRklFTERfTlVNQkVSID0gNTM2ODcwMDA5OwogICAgICBwcml2YXRlIGludCBncm91cEFfID0gMDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGdyb3VwX2EgPSA1MzY4NzAwMDk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGdyb3VwQSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0dyb3VwQSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGdyb3VwX2EgPSA1MzY4NzAwMDk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBncm91cEEuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0R3JvdXBBKCkgewogICAgICAgIHJldHVybiBncm91cEFfOwogICAgICB9CgogICAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoNTM2ODcwMDA5LCBncm91cEFfKTsKICAgICAgICB9CiAgICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgICAgc2l6ZSA9IDA7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoNTM2ODcwMDA5LCBncm91cEFfKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICAgIHJldHVybiBzaXplOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXApKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgICAgfQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwKSBvYmo7CgogICAgICAgIGlmIChoYXNHcm91cEEoKSAhPSBvdGhlci5oYXNHcm91cEEoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChoYXNHcm91cEEoKSkgewogICAgICAgICAgaWYgKGdldEdyb3VwQSgpCiAgICAgICAgICAgICAgIT0gb3RoZXIuZ2V0R3JvdXBBKCkpIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICAgIH0KICAgICAgICBpbnQgaGFzaCA9IDQxOwogICAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICAgIGlmIChoYXNHcm91cEEoKSkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgR1JPVVBfQV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRHcm91cEEoKTsKICAgICAgICB9CiAgICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgICAgcmV0dXJuIGhhc2g7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcHJvdG90eXBlKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlciB7CiAgICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9PcHRpb25hbEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAubmV3QnVpbGRlcigpCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBncm91cEFfID0gMDsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBidWlsZCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAodGhpcyk7CiAgICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgICAgb25CdWlsdCgpOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHJlc3VsdCkgewogICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICByZXN1bHQuZ3JvdXBBXyA9IGdyb3VwQV87CiAgICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCkgewogICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cClvdGhlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICAgIGlmIChvdGhlci5oYXNHcm91cEEoKSkgewogICAgICAgICAgICBzZXRHcm91cEEob3RoZXIuZ2V0R3JvdXBBKCkpOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAtNzIyNDogewogICAgICAgICAgICAgICAgICBncm91cEFfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyMjQKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgIHByaXZhdGUgaW50IGdyb3VwQV8gOwogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGdyb3VwX2EgPSA1MzY4NzAwMDk7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZ3JvdXBBIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzR3JvdXBBKCkgewogICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBncm91cF9hID0gNTM2ODcwMDA5OzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBncm91cEEuCiAgICAgICAgICovCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgZ2V0R3JvdXBBKCkgewogICAgICAgICAgcmV0dXJuIGdyb3VwQV87CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGdyb3VwX2EgPSA1MzY4NzAwMDk7PC9jb2RlPgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZ3JvdXBBIHRvIHNldC4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0R3JvdXBBKGludCB2YWx1ZSkgewoKICAgICAgICAgIGdyb3VwQV8gPSB2YWx1ZTsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGdyb3VwX2EgPSA1MzY4NzAwMDk7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckdyb3VwQSgpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgIGdyb3VwQV8gPSAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgoKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgIH0KCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIHN0YXRpYyB7CiAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cD4KICAgICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPE9wdGlvbmFsR3JvdXA+KCkgewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgT3B0aW9uYWxHcm91cCBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE9wdGlvbmFsR3JvdXA+IHBhcnNlcigpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxPcHRpb25hbEdyb3VwPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHByaXZhdGUgaW50IG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBvbmVvZkZpZWxkXzsKICAgIHB1YmxpYyBlbnVtIE9uZW9mRmllbGRDYXNlCiAgICAgICAgaW1wbGVtZW50cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlLAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZS5JbnRlcm5hbE9uZU9mRW51bSB7CiAgICAgIE9ORU9GX1VJTlQzMig1MzY4NzAwMTEpLAogICAgICBPTkVPRl9URVNUX0FMTF9UWVBFUyg1MzY4NzAwMTIpLAogICAgICBPTkVPRl9TVFJJTkcoNTM2ODcwMDEzKSwKICAgICAgT05FT0ZfQllURVMoNTM2ODcwMDE0KSwKICAgICAgT05FT0ZGSUVMRF9OT1RfU0VUKDApOwogICAgICBwcml2YXRlIGZpbmFsIGludCB2YWx1ZTsKICAgICAgcHJpdmF0ZSBPbmVvZkZpZWxkQ2FzZShpbnQgdmFsdWUpIHsKICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtYmVyIG9mIHRoZSBlbnVtIHRvIGxvb2sgZm9yLgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtYmVyLgogICAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgc3RhdGljIE9uZW9mRmllbGRDYXNlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgT25lb2ZGaWVsZENhc2UgZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICAgIGNhc2UgNTM2ODcwMDExOiByZXR1cm4gT05FT0ZfVUlOVDMyOwogICAgICAgICAgY2FzZSA1MzY4NzAwMTI6IHJldHVybiBPTkVPRl9URVNUX0FMTF9UWVBFUzsKICAgICAgICAgIGNhc2UgNTM2ODcwMDEzOiByZXR1cm4gT05FT0ZfU1RSSU5HOwogICAgICAgICAgY2FzZSA1MzY4NzAwMTQ6IHJldHVybiBPTkVPRl9CWVRFUzsKICAgICAgICAgIGNhc2UgMDogcmV0dXJuIE9ORU9GRklFTERfTk9UX1NFVDsKICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE51bWJlcigpIHsKICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgT25lb2ZGaWVsZENhc2UKICAgIGdldE9uZW9mRmllbGRDYXNlKCkgewogICAgICByZXR1cm4gT25lb2ZGaWVsZENhc2UuZm9yTnVtYmVyKAogICAgICAgICAgb25lb2ZGaWVsZENhc2VfKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9JTlQzMl9GSUVMRF9OVU1CRVIgPSA1MzY4NzAwMDA7CiAgICBwcml2YXRlIGludCBvcHRpb25hbEludDMyXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gNTM2ODcwMDAwOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW50MzIoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSA1MzY4NzAwMDA7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRPcHRpb25hbEludDMyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxJbnQzMl87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRklYRURfMzJfRklFTERfTlVNQkVSID0gNTM2ODcwMDAxOwogICAgcHJpdmF0ZSBpbnQgZml4ZWQzMl8gPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBmaXhlZF8zMiA9IDUzNjg3MDAwMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNGaXhlZDMyKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGZpeGVkXzMyID0gNTM2ODcwMDAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGZpeGVkMzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0Rml4ZWQzMigpIHsKICAgICAgcmV0dXJuIGZpeGVkMzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAwMjsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRJbnQzMl8gPQogICAgICAgIGVtcHR5SW50TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRSZXBlYXRlZEludDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfLmdldEludChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAwMzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkSW50MzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRJbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFBhY2tlZEludDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRJbnQzMi4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkSW50MzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkSW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfRU5VTV9GSUVMRF9OVU1CRVIgPSA1MzY4NzAwMDQ7CiAgICBwcml2YXRlIGludCBvcHRpb25hbEVudW1fID0gNDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZW51bSA9IDUzNjg3MDAwNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxFbnVtKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIG9wdGlvbmFsX2VudW0gPSA1MzY4NzAwMDQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgZ2V0T3B0aW9uYWxFbnVtKCkgewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcihvcHRpb25hbEVudW1fKTsKICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLkZPUkVJR05fTElURV9GT08gOiByZXN1bHQ7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfU1RSSU5HX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAwNTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSB2b2xhdGlsZSBqYXZhLmxhbmcuT2JqZWN0IG9wdGlvbmFsU3RyaW5nXyA9ICIiOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gNTM2ODcwMDA1OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFN0cmluZygpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gNTM2ODcwMDA1OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU3RyaW5nLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPcHRpb25hbFN0cmluZygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ187CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gCiAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgb3B0aW9uYWxTdHJpbmdfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxTdHJpbmcuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPcHRpb25hbFN0cmluZ0J5dGVzKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IG9wdGlvbmFsU3RyaW5nXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgb3B0aW9uYWxTdHJpbmdfID0gYjsKICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfQllURVNfRklFTERfTlVNQkVSID0gNTM2ODcwMDA2OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgb3B0aW9uYWxCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIG9wdGlvbmFsX2J5dGVzID0gNTM2ODcwMDA2OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsQnl0ZXMoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSA1MzY4NzAwMDY7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxCeXRlcy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPcHRpb25hbEJ5dGVzKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxCeXRlc187CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSA1MzY4NzAwMDc7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbE1lc3NhZ2VfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxNZXNzYWdlKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxNZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldE9wdGlvbmFsTWVzc2FnZSgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsTWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsTWVzc2FnZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsTWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsTWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsTWVzc2FnZV87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxHUk9VUF9GSUVMRF9OVU1CRVIgPSA1MzY4NzAwMDg7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIG9wdGlvbmFsR3JvdXBfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gNTM2ODcwMDA4IHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsZ3JvdXAgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEdyb3VwKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsZ3JvdXAuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxHcm91cF8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxHcm91cF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBTVFJJTkdfU1RSSU5HX01BUF9GSUVMRF9OVU1CRVIgPSA1MzY4NzAwMTA7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBTdHJpbmdTdHJpbmdNYXBEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX1N0cmluZ1N0cmluZ01hcEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNUUklORywKICAgICAgICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU1RSSU5HLAogICAgICAgICAgICAgICAgICAiIik7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBzdHJpbmdTdHJpbmdNYXBfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICBpbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgaWYgKHN0cmluZ1N0cmluZ01hcF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIFN0cmluZ1N0cmluZ01hcERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBzdHJpbmdTdHJpbmdNYXBfOwogICAgfQogICAgcHVibGljIGludCBnZXRTdHJpbmdTdHJpbmdNYXBDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNTdHJpbmdTdHJpbmdNYXAoCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgIHJldHVybiBpbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldFN0cmluZ1N0cmluZ01hcE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IGdldFN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgcmV0dXJuIGdldFN0cmluZ1N0cmluZ01hcE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0U3RyaW5nU3RyaW5nTWFwTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBzdHJpbmdfc3RyaW5nX21hcCA9IDUzNjg3MDAxMDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGdldFN0cmluZ1N0cmluZ01hcE9yRGVmYXVsdCgKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewogICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0U3RyaW5nU3RyaW5nTWFwT3JUaHJvdygKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSkgewogICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9VSU5UMzJfRklFTERfTlVNQkVSID0gNTM2ODcwMDExOwogICAgLyoqCiAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gNTM2ODcwMDExOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlVpbnQzMigpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTE7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSA1MzY4NzAwMTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZVaW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0T25lb2ZVaW50MzIoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDExKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfVEVTVF9BTExfVFlQRVNfRklFTERfTlVNQkVSID0gNTM2ODcwMDEyOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlRlc3RBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mVGVzdEFsbFR5cGVzKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMjsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mVGVzdEFsbFR5cGVzLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRPbmVvZlRlc3RBbGxUeXBlcygpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTIpIHsKICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T25lb2ZUZXN0QWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfU1RSSU5HX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAxMzsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZTdHJpbmcoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEzOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gNTM2ODcwMDEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTMpIHsKICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkgJiYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTMpKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSA1MzY4NzAwMTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTMpIHsKICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMykgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBiOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfQllURVNfRklFTERfTlVNQkVSID0gNTM2ODcwMDE0OwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDUzNjg3MDAxNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxNDsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA1MzY4NzAwMTQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlcy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPbmVvZkJ5dGVzKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxNCkgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmICghZXh0ZW5zaW9uc0FyZUluaXRpYWxpemVkKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLkV4dGVuZGFibGVNZXNzYWdlPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZT4uRXh0ZW5zaW9uV3JpdGVyCiAgICAgICAgICBleHRlbnNpb25Xcml0ZXIgPSBuZXdFeHRlbnNpb25Xcml0ZXIoKTsKICAgICAgZXh0ZW5zaW9uV3JpdGVyLndyaXRlVW50aWwoNTM2ODcwMDAwLCBvdXRwdXQpOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMig1MzY4NzAwMDAsIG9wdGlvbmFsSW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMig1MzY4NzAwMDEsIGZpeGVkMzJfKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkSW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoNTM2ODcwMDAyLCByZXBlYXRlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRJbnQzMkxpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoLTcyNzApOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZEludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMk5vVGFnKHBhY2tlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oNTM2ODcwMDA0LCBvcHRpb25hbEVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDUzNjg3MDAwNSwgb3B0aW9uYWxTdHJpbmdfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVCeXRlcyg1MzY4NzAwMDYsIG9wdGlvbmFsQnl0ZXNfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDUzNjg3MDAwNywgZ2V0T3B0aW9uYWxNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUdyb3VwKDUzNjg3MDAwOCwgZ2V0T3B0aW9uYWxHcm91cCgpKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVTdHJpbmdNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCksCiAgICAgICAgICBTdHJpbmdTdHJpbmdNYXBEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgNTM2ODcwMDEwKTsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTEpIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzIoCiAgICAgICAgICAgIDUzNjg3MDAxMSwgKGludCkoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSg1MzY4NzAwMTIsIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTMpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDUzNjg3MDAxMywgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDE0KSB7CiAgICAgICAgb3V0cHV0LndyaXRlQnl0ZXMoCiAgICAgICAgICAgIDUzNjg3MDAxNCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDUzNjg3MDAwMCwgb3B0aW9uYWxJbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoNTM2ODcwMDAxLCBmaXhlZDMyXyk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKHJlcGVhdGVkSW50MzJfLmdldEludChpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSA1ICogZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhwYWNrZWRJbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZEludDMyTGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSA1OwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZEludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZSg1MzY4NzAwMDQsIG9wdGlvbmFsRW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoNTM2ODcwMDA1LCBvcHRpb25hbFN0cmluZ18pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemUoNTM2ODcwMDA2LCBvcHRpb25hbEJ5dGVzXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDUzNjg3MDAwNywgZ2V0T3B0aW9uYWxNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVHcm91cFNpemUoNTM2ODcwMDA4LCBnZXRPcHRpb25hbEdyb3VwKCkpOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgIHN0cmluZ1N0cmluZ01hcF9fID0gU3RyaW5nU3RyaW5nTWFwRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg1MzY4NzAwMTAsIHN0cmluZ1N0cmluZ01hcF9fKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVVSW50MzJTaXplKAogICAgICAgICAgICAgIDUzNjg3MDAxMSwgKGludCkoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDUzNjg3MDAxMiwgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoNTM2ODcwMDEzLCBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTQpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlQnl0ZXNTaXplKAogICAgICAgICAgICAgIDUzNjg3MDAxNCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIHNpemUgKz0gZXh0ZW5zaW9uc1NlcmlhbGl6ZWRTaXplKCk7CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc09wdGlvbmFsSW50MzIoKSAhPSBvdGhlci5oYXNPcHRpb25hbEludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsSW50MzIoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbEludDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T3B0aW9uYWxJbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0ZpeGVkMzIoKSAhPSBvdGhlci5oYXNGaXhlZDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0ZpeGVkMzIoKSkgewogICAgICAgIGlmIChnZXRGaXhlZDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0Rml4ZWQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFnZXRSZXBlYXRlZEludDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkSW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkSW50MzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkSW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEVudW0oKSAhPSBvdGhlci5oYXNPcHRpb25hbEVudW0oKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxFbnVtKCkpIHsKICAgICAgICBpZiAob3B0aW9uYWxFbnVtXyAhPSBvdGhlci5vcHRpb25hbEVudW1fKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU3RyaW5nKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxTdHJpbmcoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxTdHJpbmcoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxTdHJpbmcoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsU3RyaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQnl0ZXMoKSAhPSBvdGhlci5oYXNPcHRpb25hbEJ5dGVzKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsQnl0ZXMoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxCeXRlcygpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxCeXRlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbE1lc3NhZ2UoKSAhPSBvdGhlci5oYXNPcHRpb25hbE1lc3NhZ2UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxNZXNzYWdlKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsTWVzc2FnZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxNZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSAhPSBvdGhlci5oYXNPcHRpb25hbEdyb3VwKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxHcm91cCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxHcm91cCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldE9uZW9mRmllbGRDYXNlKCkuZXF1YWxzKG90aGVyLmdldE9uZW9mRmllbGRDYXNlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHN3aXRjaCAob25lb2ZGaWVsZENhc2VfKSB7CiAgICAgICAgY2FzZSA1MzY4NzAwMTE6CiAgICAgICAgICBpZiAoZ2V0T25lb2ZVaW50MzIoKQogICAgICAgICAgICAgICE9IG90aGVyLmdldE9uZW9mVWludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNTM2ODcwMDEyOgogICAgICAgICAgaWYgKCFnZXRPbmVvZlRlc3RBbGxUeXBlcygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZlRlc3RBbGxUeXBlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1MzY4NzAwMTM6CiAgICAgICAgICBpZiAoIWdldE9uZW9mU3RyaW5nKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mU3RyaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDUzNjg3MDAxNDoKICAgICAgICAgIGlmICghZ2V0T25lb2ZCeXRlcygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZkJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDA6CiAgICAgICAgZGVmYXVsdDoKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldEV4dGVuc2lvbkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRFeHRlbnNpb25GaWVsZHMoKSkpCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNPcHRpb25hbEludDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxJbnQzMigpOwogICAgICB9CiAgICAgIGlmIChoYXNGaXhlZDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBGSVhFRF8zMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0Rml4ZWQzMigpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEludDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRJbnQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRJbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEVudW0oKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIG9wdGlvbmFsRW51bV87CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU3RyaW5nKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9TVFJJTkdfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsU3RyaW5nKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxCeXRlcygpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfQllURVNfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsQnl0ZXMoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbE1lc3NhZ2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsTWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMR1JPVVBfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsR3JvdXAoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBTVFJJTkdfU1RSSU5HX01BUF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIHN3aXRjaCAob25lb2ZGaWVsZENhc2VfKSB7CiAgICAgICAgY2FzZSA1MzY4NzAwMTE6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9VSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZVaW50MzIoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNTM2ODcwMDEyOgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfVEVTVF9BTExfVFlQRVNfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZUZXN0QWxsVHlwZXMoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1MzY4NzAwMTM6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9TVFJJTkdfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZTdHJpbmcoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1MzY4NzAwMTQ6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9CWVRFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZkJ5dGVzKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMDoKICAgICAgICBkZWZhdWx0OgogICAgICB9CiAgICAgIGhhc2ggPSBoYXNoRmllbGRzKGhhc2gsIGdldEV4dGVuc2lvbkZpZWxkcygpKTsKICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUsIEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgNTM2ODcwMDEwOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDUzNjg3MDAxMDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKICAgICAgICBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCk7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgaWYgKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgICAuYWx3YXlzVXNlRmllbGRCdWlsZGVycykgewogICAgICAgICAgZ2V0T3B0aW9uYWxNZXNzYWdlRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwRmllbGRCdWlsZGVyKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBvcHRpb25hbEludDMyXyA9IDA7CiAgICAgICAgZml4ZWQzMl8gPSAwOwogICAgICAgIHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgcGFja2VkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgb3B0aW9uYWxFbnVtXyA9IDQ7CiAgICAgICAgb3B0aW9uYWxTdHJpbmdfID0gIiI7CiAgICAgICAgb3B0aW9uYWxCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFk7CiAgICAgICAgb3B0aW9uYWxNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3B0aW9uYWxHcm91cF8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpLmNsZWFyKCk7CiAgICAgICAgaWYgKG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBidWlsZFBhcnRpYWxPbmVvZnMocmVzdWx0KTsKICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsSW50MzJfID0gb3B0aW9uYWxJbnQzMl87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZml4ZWQzMl8gPSBmaXhlZDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEludDMyXyA9IHJlcGVhdGVkSW50MzJfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgICAgcGFja2VkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRJbnQzMl8gPSBwYWNrZWRJbnQzMl87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxFbnVtXyA9IG9wdGlvbmFsRW51bV87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxTdHJpbmdfID0gb3B0aW9uYWxTdHJpbmdfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsQnl0ZXNfID0gb3B0aW9uYWxCeXRlc187CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxNZXNzYWdlXyA9IG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsTWVzc2FnZV8KICAgICAgICAgICAgICA6IG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAxMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxHcm91cF8gPSBvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gb3B0aW9uYWxHcm91cF8KICAgICAgICAgICAgICA6IG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMjAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LnN0cmluZ1N0cmluZ01hcF8gPSBpbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpOwogICAgICAgICAgcmVzdWx0LnN0cmluZ1N0cmluZ01hcF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsT25lb2ZzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSByZXN1bHQpIHsKICAgICAgICByZXN1bHQub25lb2ZGaWVsZENhc2VfID0gb25lb2ZGaWVsZENhc2VfOwogICAgICAgIHJlc3VsdC5vbmVvZkZpZWxkXyA9IHRoaXMub25lb2ZGaWVsZF87CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTIgJiYKICAgICAgICAgICAgb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXN1bHQub25lb2ZGaWVsZF8gPSBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgc2V0RXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUsIFR5cGU+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIHNldEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgaW50IGluZGV4LCBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgYWRkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUsIGphdmEudXRpbC5MaXN0PFR5cGU+PiBleHRlbnNpb24sCiAgICAgICAgICBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZEV4dGVuc2lvbihleHRlbnNpb24sIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VD4gQnVpbGRlciBjbGVhckV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLCBUPiBleHRlbnNpb24pIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJFeHRlbnNpb24oZXh0ZW5zaW9uKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxJbnQzMigpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEludDMyKG90aGVyLmdldE9wdGlvbmFsSW50MzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNGaXhlZDMyKCkpIHsKICAgICAgICAgIHNldEZpeGVkMzIob3RoZXIuZ2V0Rml4ZWQzMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBvdGhlci5yZXBlYXRlZEludDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZEludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRJbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWRJbnQzMl8gPSBvdGhlci5wYWNrZWRJbnQzMl87CiAgICAgICAgICAgIHBhY2tlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZEludDMyXy5hZGRBbGwob3RoZXIucGFja2VkSW50MzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxFbnVtKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsRW51bShvdGhlci5nZXRPcHRpb25hbEVudW0oKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbFN0cmluZygpKSB7CiAgICAgICAgICBvcHRpb25hbFN0cmluZ18gPSBvdGhlci5vcHRpb25hbFN0cmluZ187CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsQnl0ZXMoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxCeXRlcyhvdGhlci5nZXRPcHRpb25hbEJ5dGVzKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxNZXNzYWdlKCkpIHsKICAgICAgICAgIG1lcmdlT3B0aW9uYWxNZXNzYWdlKG90aGVyLmdldE9wdGlvbmFsTWVzc2FnZSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbEdyb3VwKG90aGVyLmdldE9wdGlvbmFsR3JvdXAoKSk7CiAgICAgICAgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIHN3aXRjaCAob3RoZXIuZ2V0T25lb2ZGaWVsZENhc2UoKSkgewogICAgICAgICAgY2FzZSBPTkVPRl9VSU5UMzI6IHsKICAgICAgICAgICAgc2V0T25lb2ZVaW50MzIob3RoZXIuZ2V0T25lb2ZVaW50MzIoKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9URVNUX0FMTF9UWVBFUzogewogICAgICAgICAgICBtZXJnZU9uZW9mVGVzdEFsbFR5cGVzKG90aGVyLmdldE9uZW9mVGVzdEFsbFR5cGVzKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfU1RSSU5HOiB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDUzNjg3MDAxMzsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBvdGhlci5vbmVvZkZpZWxkXzsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9CWVRFUzogewogICAgICAgICAgICBzZXRPbmVvZkJ5dGVzKG90aGVyLmdldE9uZW9mQnl0ZXMoKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRkZJRUxEX05PVF9TRVQ6IHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VFeHRlbnNpb25GaWVsZHMob3RoZXIpOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBpZiAoIWV4dGVuc2lvbnNBcmVJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAtNzI5NjogewogICAgICAgICAgICAgICAgb3B0aW9uYWxJbnQzMl8gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzI5NgogICAgICAgICAgICAgIGNhc2UgLTcyODg6IHsKICAgICAgICAgICAgICAgIGZpeGVkMzJfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyODgKICAgICAgICAgICAgICBjYXNlIC03MjgwOiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03MjgwCiAgICAgICAgICAgICAgY2FzZSAtNzI3ODogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludChpbnB1dC5yZWFkSW50MzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyNzgKICAgICAgICAgICAgICBjYXNlIC03MjcyOiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHBhY2tlZEludDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyNzIKICAgICAgICAgICAgICBjYXNlIC03MjcwOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHBhY2tlZEludDMyXy5hZGRJbnQoaW5wdXQucmVhZEludDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03MjcwCiAgICAgICAgICAgICAgY2FzZSAtNzI2NDogewogICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDUzNjg3MDAwNCwgdG1wUmF3KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIG9wdGlvbmFsRW51bV8gPSB0bXBSYXc7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzI2NAogICAgICAgICAgICAgIGNhc2UgLTcyNTQ6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03MjU0CiAgICAgICAgICAgICAgY2FzZSAtNzI0NjogewogICAgICAgICAgICAgICAgb3B0aW9uYWxCeXRlc18gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzI0NgogICAgICAgICAgICAgIGNhc2UgLTcyMzg6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsTWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyMzgKICAgICAgICAgICAgICBjYXNlIC03MjI5OiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoNTM2ODcwMDA4LAogICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03MjI5CiAgICAgICAgICAgICAgY2FzZSAtNzIxNDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgICAgICAgICAgc3RyaW5nU3RyaW5nTWFwX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBTdHJpbmdTdHJpbmdNYXBEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBzdHJpbmdTdHJpbmdNYXBfXy5nZXRLZXkoKSwgc3RyaW5nU3RyaW5nTWFwX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyMTQKICAgICAgICAgICAgICBjYXNlIC03MjA4OiB7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGlucHV0LnJlYWRVSW50MzIoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDUzNjg3MDAxMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzIwOAogICAgICAgICAgICAgIGNhc2UgLTcxOTg6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9uZW9mVGVzdEFsbFR5cGVzRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDUzNjg3MDAxMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzE5OAogICAgICAgICAgICAgIGNhc2UgLTcxOTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDEzOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBiczsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzE5MAogICAgICAgICAgICAgIGNhc2UgLTcxODI6IHsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1MzY4NzAwMTQ7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcxODIKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3Qgb25lb2ZGaWVsZF87CiAgICAgIHB1YmxpYyBPbmVvZkZpZWxkQ2FzZQogICAgICAgICAgZ2V0T25lb2ZGaWVsZENhc2UoKSB7CiAgICAgICAgcmV0dXJuIE9uZW9mRmllbGRDYXNlLmZvck51bWJlcigKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfKTsKICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkZpZWxkKCkgewogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxJbnQzMl8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSA1MzY4NzAwMDA7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEludDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSA1MzY4NzAwMDA7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEludDMyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE9wdGlvbmFsSW50MzIoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsSW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBvcHRpb25hbF9pbnQzMiA9IDUzNjg3MDAwMDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxJbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsSW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsSW50MzJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBvcHRpb25hbF9pbnQzMiA9IDUzNjg3MDAwMDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxJbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgb3B0aW9uYWxJbnQzMl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBmaXhlZDMyXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBmaXhlZF8zMiA9IDUzNjg3MDAwMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZml4ZWQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0ZpeGVkMzIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBmaXhlZF8zMiA9IDUzNjg3MDAwMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGZpeGVkMzIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0Rml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gZml4ZWQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGZpeGVkXzMyID0gNTM2ODcwMDAxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBmaXhlZDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0Rml4ZWQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZml4ZWQzMl8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGZpeGVkXzMyID0gNTM2ODcwMDAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaXhlZDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICBmaXhlZDMyXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRJbnQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW50MzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkSW50MzJfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFJlcGVhdGVkSW50MzJMaXN0KCkgewogICAgICAgIHJlcGVhdGVkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSA1MzY4NzAwMDIgW3BhY2tlZCA9IGZhbHNlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSA1MzY4NzAwMDIgW3BhY2tlZCA9IGZhbHNlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRJbnQzMigKICAgICAgICAgIGludCBpbmRleCwgaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEludDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkSW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRJbnQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRJbnQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSA1MzY4NzAwMDIgW3BhY2tlZCA9IGZhbHNlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRJbnQzMigpIHsKICAgICAgICByZXBlYXRlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZEludDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkSW50MzJfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZEludDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UGFja2VkSW50MzJMaXN0KCkgewogICAgICAgIHBhY2tlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHBhY2tlZEludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBwYWNrZWRJbnQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA1MzY4NzAwMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkSW50MzIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA1MzY4NzAwMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkSW50MzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEludDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDUzNjg3MDAwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkSW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkSW50MzJfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA1MzY4NzAwMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkSW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRJbnQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZEludDMyXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA1MzY4NzAwMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRJbnQzMigpIHsKICAgICAgICBwYWNrZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwOCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IG9wdGlvbmFsRW51bV8gPSA0OwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZW51bSA9IDUzNjg3MDAwNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxFbnVtIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxFbnVtKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZW51bSA9IDUzNjg3MDAwNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRW51bS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRPcHRpb25hbEVudW0oKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIob3B0aW9uYWxFbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLkZPUkVJR05fTElURV9GT08gOiByZXN1bHQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIG9wdGlvbmFsX2VudW0gPSA1MzY4NzAwMDQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsRW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsRW51bShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICBvcHRpb25hbEVudW1fID0gdmFsdWUuZ2V0TnVtYmVyKCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIG9wdGlvbmFsX2VudW0gPSA1MzY4NzAwMDQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsRW51bSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgb3B0aW9uYWxFbnVtXyA9IDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDIwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU3RyaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T3B0aW9uYWxTdHJpbmcoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ187CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICBvcHRpb25hbFN0cmluZ18gPSBzOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldE9wdGlvbmFsU3RyaW5nQnl0ZXMoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ187CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGI7CiAgICAgICAgICByZXR1cm4gYjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbFN0cmluZ18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsU3RyaW5nKCkgewogICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGdldERlZmF1bHRJbnN0YW5jZSgpLmdldE9wdGlvbmFsU3RyaW5nKCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMjApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gNTM2ODcwMDA1OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFN0cmluZ0J5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbFN0cmluZ18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIG9wdGlvbmFsQnl0ZXNfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSA1MzY4NzAwMDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEJ5dGVzKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSA1MzY4NzAwMDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEJ5dGVzLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9wdGlvbmFsQnl0ZXMoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsQnl0ZXNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDUzNjg3MDAwNjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxCeXRlcyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsQnl0ZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbEJ5dGVzXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSA1MzY4NzAwMDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsQnl0ZXMoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwNDApOwogICAgICAgIG9wdGlvbmFsQnl0ZXNfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0T3B0aW9uYWxCeXRlcygpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbE1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+IG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsTWVzc2FnZSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDA4MCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbE1lc3NhZ2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldE9wdGlvbmFsTWVzc2FnZSgpIHsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsTWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsTWVzc2FnZV87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvcHRpb25hbE1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxNZXNzYWdlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZU9wdGlvbmFsTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwODApICE9IDApICYmCiAgICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZV8gIT0gbnVsbCAmJgogICAgICAgICAgICBvcHRpb25hbE1lc3NhZ2VfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbE1lc3NhZ2VCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsTWVzc2FnZV8gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxNZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDgwKTsKICAgICAgICBvcHRpb25hbE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIgZ2V0T3B0aW9uYWxNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsTWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsTWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsTWVzc2FnZV8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxNZXNzYWdlXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsTWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbE1lc3NhZ2UoKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgb3B0aW9uYWxHcm91cF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlcj4gb3B0aW9uYWxHcm91cEJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDUzNjg3MDAwOCB7IC4uLiB9PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsZ3JvdXAgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxncm91cC4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsR3JvdXAoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxHcm91cChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAxMDApICE9IDApICYmCiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxHcm91cF8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEJ1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbEdyb3VwXyAhPSBudWxsKSB7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxHcm91cCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDEwMCk7CiAgICAgICAgb3B0aW9uYWxHcm91cF8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gNTM2ODcwMDA4IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciBnZXRPcHRpb25hbEdyb3VwQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlciBnZXRPcHRpb25hbEdyb3VwT3JCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwXyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDUzNjg3MDAwOCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvcHRpb25hbEdyb3VwXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IHN0cmluZ1N0cmluZ01hcF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgICAgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKSB7CiAgICAgICAgaWYgKHN0cmluZ1N0cmluZ01hcF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBTdHJpbmdTdHJpbmdNYXBEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHN0cmluZ1N0cmluZ01hcF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVTdHJpbmdTdHJpbmdNYXAoKSB7CiAgICAgICAgaWYgKHN0cmluZ1N0cmluZ01hcF8gPT0gbnVsbCkgewogICAgICAgICAgc3RyaW5nU3RyaW5nTWFwXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgU3RyaW5nU3RyaW5nTWFwRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghc3RyaW5nU3RyaW5nTWFwXy5pc011dGFibGUoKSkgewogICAgICAgICAgc3RyaW5nU3RyaW5nTWFwXyA9IHN0cmluZ1N0cmluZ01hcF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHN0cmluZ1N0cmluZ01hcF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRTdHJpbmdTdHJpbmdNYXBDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgc3RyaW5nX3N0cmluZ19tYXAgPSA1MzY4NzAwMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc1N0cmluZ1N0cmluZ01hcCgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0U3RyaW5nU3RyaW5nTWFwTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBnZXRTdHJpbmdTdHJpbmdNYXAoKSB7CiAgICAgICAgcmV0dXJuIGdldFN0cmluZ1N0cmluZ01hcE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0U3RyaW5nU3RyaW5nTWFwTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZ2V0U3RyaW5nU3RyaW5nTWFwT3JEZWZhdWx0KAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgc3RyaW5nX3N0cmluZ19tYXAgPSA1MzY4NzAwMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRTdHJpbmdTdHJpbmdNYXBPclRocm93KAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDIwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVN0cmluZ1N0cmluZ01hcCgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgICAgZ2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBzdHJpbmdfc3RyaW5nX21hcCA9IDUzNjg3MDAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRTdHJpbmdTdHJpbmdNYXAoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSwKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCB2YWx1ZSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbFN0cmluZ1N0cmluZ01hcCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gNTM2ODcwMDExOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlVpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlVpbnQzMigpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+dWludDMyIG9uZW9mX3VpbnQzMiA9IDUzNjg3MDAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mVWludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRPbmVvZlVpbnQzMigpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMSkgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIHJldHVybiAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gNTM2ODcwMDExOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvbmVvZlVpbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mVWludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1MzY4NzAwMTE7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+dWludDMyIG9uZW9mX3VpbnQzMiA9IDUzNjg3MDAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZVaW50MzIoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTEpIHsKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZUZXN0QWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlRlc3RBbGxUeXBlcygpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMjsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZUZXN0QWxsVHlwZXMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE9uZW9mVGVzdEFsbFR5cGVzKCkgewogICAgICAgIGlmIChvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF87CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTIpIHsKICAgICAgICAgICAgcmV0dXJuIG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZUZXN0QWxsVHlwZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1MzY4NzAwMTI7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlRlc3RBbGxUeXBlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDUzNjg3MDAxMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT25lb2ZUZXN0QWxsVHlwZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyICYmCiAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUubmV3QnVpbGRlcigoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF8pCiAgICAgICAgICAgICAgICAubWVyZ2VGcm9tKHZhbHVlKS5idWlsZFBhcnRpYWwoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTIpIHsKICAgICAgICAgICAgb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDEyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlRlc3RBbGxUeXBlcygpIHsKICAgICAgICBpZiAob25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMikgewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMikgewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRPbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIGdldE9uZW9mVGVzdEFsbFR5cGVzRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRPbmVvZlRlc3RBbGxUeXBlc09yQnVpbGRlcigpIHsKICAgICAgICBpZiAoKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTIpICYmIChvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfICE9IG51bGwpKSB7CiAgICAgICAgICByZXR1cm4gb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF87CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T25lb2ZUZXN0QWxsVHlwZXNGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCEob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMikpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXywKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDEyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlN0cmluZygpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEzKSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMykgewogICAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gczsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEzKSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEzKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYjsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN0cmluZygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDUzNjg3MDAxMzsKICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gNTM2ODcwMDEzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlN0cmluZygpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMykgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZTdHJpbmdCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDEzOwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDUzNjg3MDAxNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDE0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDUzNjg3MDAxNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mQnl0ZXMuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXMoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTQpIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA1MzY4NzAwMTQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mQnl0ZXMgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZkJ5dGVzKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDE0OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNTM2ODcwMDE0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkJ5dGVzKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDE0KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdE9uZW9mUGFyc2luZ0xpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RPbmVvZlBhcnNpbmdMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+aW50MzIgb25lb2ZfaW50MzIgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZJbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5pbnQzMiBvbmVvZl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZJbnQzMi4KICAgICAqLwogICAgaW50IGdldE9uZW9mSW50MzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3VibWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZTdWJtZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN1Ym1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T25lb2ZTdWJtZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T25lb2ZTdWJtZXNzYWdlT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZlN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZy4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9uZW9mU3RyaW5nQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNCBbZGVmYXVsdCA9ICJkZWZhdWx0IGJ5dGVzIl07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNCBbZGVmYXVsdCA9ICJkZWZhdWx0IGJ5dGVzIl07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlcy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZTdHJpbmdDb3JkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZ0NvcmQuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmdDb3JkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdDb3JkLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPbmVvZlN0cmluZ0NvcmRCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZCeXRlc0NvcmQoKTsKICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlc0NvcmQuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPbmVvZkJ5dGVzQ29yZCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfc3RyaW5nX3BpZWNlID0gNyBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdTdHJpbmdQaWVjZS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZUJ5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19zdHJpbmdfcGllY2UgPSA4IFtkZWZhdWx0ID0gImRlZmF1bHQgU3RyaW5nUGllY2UiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzU3RyaW5nUGllY2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mQnl0ZXNTdHJpbmdQaWVjZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19zdHJpbmdfcGllY2UgPSA4IFtkZWZhdWx0ID0gImRlZmF1bHQgU3RyaW5nUGllY2UiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlc1N0cmluZ1BpZWNlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlYyRW51bUxpdGUgb25lb2ZfZW51bSA9IDk7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mRW51bSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlYyRW51bUxpdGUgb25lb2ZfZW51bSA9IDk7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZFbnVtLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIGdldE9uZW9mRW51bSgpOwoKICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlLk9uZW9mRmllbGRDYXNlIGdldE9uZW9mRmllbGRDYXNlKCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0T25lb2ZQYXJzaW5nTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RPbmVvZlBhcnNpbmdMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0T25lb2ZQYXJzaW5nTGl0ZSkKICAgICAgVGVzdE9uZW9mUGFyc2luZ0xpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RPbmVvZlBhcnNpbmdMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RPbmVvZlBhcnNpbmdMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdE9uZW9mUGFyc2luZ0xpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdE9uZW9mUGFyc2luZ0xpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RPbmVvZlBhcnNpbmdMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGludCBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3Qgb25lb2ZGaWVsZF87CiAgICBwdWJsaWMgZW51bSBPbmVvZkZpZWxkQ2FzZQogICAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2UuSW50ZXJuYWxPbmVPZkVudW0gewogICAgICBPTkVPRl9JTlQzMigxKSwKICAgICAgT05FT0ZfU1VCTUVTU0FHRSgyKSwKICAgICAgT05FT0ZfU1RSSU5HKDMpLAogICAgICBPTkVPRl9CWVRFUyg0KSwKICAgICAgT05FT0ZfU1RSSU5HX0NPUkQoNSksCiAgICAgIE9ORU9GX0JZVEVTX0NPUkQoNiksCiAgICAgIE9ORU9GX1NUUklOR19TVFJJTkdfUElFQ0UoNyksCiAgICAgIE9ORU9GX0JZVEVTX1NUUklOR19QSUVDRSg4KSwKICAgICAgT05FT0ZfRU5VTSg5KSwKICAgICAgT05FT0ZGSUVMRF9OT1RfU0VUKDApOwogICAgICBwcml2YXRlIGZpbmFsIGludCB2YWx1ZTsKICAgICAgcHJpdmF0ZSBPbmVvZkZpZWxkQ2FzZShpbnQgdmFsdWUpIHsKICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtYmVyIG9mIHRoZSBlbnVtIHRvIGxvb2sgZm9yLgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtYmVyLgogICAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgc3RhdGljIE9uZW9mRmllbGRDYXNlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgT25lb2ZGaWVsZENhc2UgZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICAgIGNhc2UgMTogcmV0dXJuIE9ORU9GX0lOVDMyOwogICAgICAgICAgY2FzZSAyOiByZXR1cm4gT05FT0ZfU1VCTUVTU0FHRTsKICAgICAgICAgIGNhc2UgMzogcmV0dXJuIE9ORU9GX1NUUklORzsKICAgICAgICAgIGNhc2UgNDogcmV0dXJuIE9ORU9GX0JZVEVTOwogICAgICAgICAgY2FzZSA1OiByZXR1cm4gT05FT0ZfU1RSSU5HX0NPUkQ7CiAgICAgICAgICBjYXNlIDY6IHJldHVybiBPTkVPRl9CWVRFU19DT1JEOwogICAgICAgICAgY2FzZSA3OiByZXR1cm4gT05FT0ZfU1RSSU5HX1NUUklOR19QSUVDRTsKICAgICAgICAgIGNhc2UgODogcmV0dXJuIE9ORU9GX0JZVEVTX1NUUklOR19QSUVDRTsKICAgICAgICAgIGNhc2UgOTogcmV0dXJuIE9ORU9GX0VOVU07CiAgICAgICAgICBjYXNlIDA6IHJldHVybiBPTkVPRkZJRUxEX05PVF9TRVQ7CiAgICAgICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXROdW1iZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIE9uZW9mRmllbGRDYXNlCiAgICBnZXRPbmVvZkZpZWxkQ2FzZSgpIHsKICAgICAgcmV0dXJuIE9uZW9mRmllbGRDYXNlLmZvck51bWJlcigKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfSU5UMzJfRklFTERfTlVNQkVSID0gMTsKICAgIC8qKgogICAgICogPGNvZGU+aW50MzIgb25lb2ZfaW50MzIgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mSW50MzIoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+aW50MzIgb25lb2ZfaW50MzIgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mSW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0T25lb2ZJbnQzMigpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfU1VCTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAyOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2Zfc3VibWVzc2FnZSA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN1Ym1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlN1Ym1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMjsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3VibWVzc2FnZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T25lb2ZTdWJtZXNzYWdlKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T25lb2ZTdWJtZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9TVFJJTkdfRklFTERfTlVNQkVSID0gMzsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDM7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpICYmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMykpIHsKICAgICAgICAgIG9uZW9mRmllbGRfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IGI7CiAgICAgICAgfQogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9CWVRFU19GSUVMRF9OVU1CRVIgPSA0OwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDQgW2RlZmF1bHQgPSAiZGVmYXVsdCBieXRlcyJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mQnl0ZXMoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNDsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA0IFtkZWZhdWx0ID0gImRlZmF1bHQgYnl0ZXMiXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXMoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNCkgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5ieXRlc0RlZmF1bHRWYWx1ZSgiZGVmYXVsdCBieXRlcyIpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1NUUklOR19DT1JEX0ZJRUxEX05VTUJFUiA9IDU7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nQ29yZCgpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA1OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX2NvcmQgPSA1IFtkZWZhdWx0ID0gImRlZmF1bHQgQ29yZCIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZTdHJpbmdDb3JkLgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZ0NvcmQoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gImRlZmF1bHQgQ29yZCI7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gCiAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSAmJiAob25lb2ZGaWVsZENhc2VfID09IDUpKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdDb3JkLgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdDb3JkQnl0ZXMoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gImRlZmF1bHQgQ29yZCI7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBiOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfQllURVNfQ09SRF9GSUVMRF9OVU1CRVIgPSA2OwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19jb3JkID0gNiBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mQnl0ZXNDb3JkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZCeXRlc0NvcmQoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNjsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlc0NvcmQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlc0NvcmQoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNikgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1NUUklOR19TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSID0gNzsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZTdHJpbmdTdHJpbmdQaWVjZSgpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA3OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlLgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDcpIHsKICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkgJiYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gczsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdTdHJpbmdQaWVjZS4KICAgICAqLwogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9uZW9mU3RyaW5nU3RyaW5nUGllY2VCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSB7CiAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IGI7CiAgICAgICAgfQogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9CWVRFU19TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSID0gODsKICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfc3RyaW5nX3BpZWNlID0gOCBbZGVmYXVsdCA9ICJkZWZhdWx0IFN0cmluZ1BpZWNlIiwgY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlc1N0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDg7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzX3N0cmluZ19waWVjZSA9IDggW2RlZmF1bHQgPSAiZGVmYXVsdCBTdHJpbmdQaWVjZSIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDgpIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoImRlZmF1bHQgU3RyaW5nUGllY2UiKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9FTlVNX0ZJRUxEX05VTUJFUiA9IDk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVjJFbnVtTGl0ZSBvbmVvZl9lbnVtID0gOTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mRW51bSgpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA5OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlYyRW51bUxpdGUgb25lb2ZfZW51bSA9IDk7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZFbnVtLgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSBnZXRPbmVvZkVudW0oKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gOSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZS5mb3JOdW1iZXIoCiAgICAgICAgICAgIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF8pOwogICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuVjJfRklSU1QgOiByZXN1bHQ7CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuVjJfRklSU1Q7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDEpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigKICAgICAgICAgICAgMSwgKGludCkoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMikgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMiwgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDMpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDMsIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDQpIHsKICAgICAgICBvdXRwdXQud3JpdGVCeXRlcygKICAgICAgICAgICAgNCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgNSwgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNikgewogICAgICAgIG91dHB1dC53cml0ZUJ5dGVzKAogICAgICAgICAgICA2LCAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMud3JpdGVTdHJpbmcob3V0cHV0LCA3LCBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA4KSB7CiAgICAgICAgb3V0cHV0LndyaXRlQnl0ZXMoCiAgICAgICAgICAgIDgsIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDkpIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtKDksICgoamF2YS5sYW5nLkludGVnZXIpIG9uZW9mRmllbGRfKSk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoCiAgICAgICAgICAgICAgMSwgKGludCkoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMikgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyLCAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoMywgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNCkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemUoCiAgICAgICAgICAgICAgNCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoNSwgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNikgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemUoCiAgICAgICAgICAgICAgNiwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoNywgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gOCkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemUoCiAgICAgICAgICAgICAgOCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gOSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZSg5LCAoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFnZXRPbmVvZkZpZWxkQ2FzZSgpLmVxdWFscyhvdGhlci5nZXRPbmVvZkZpZWxkQ2FzZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBzd2l0Y2ggKG9uZW9mRmllbGRDYXNlXykgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIGlmIChnZXRPbmVvZkludDMyKCkKICAgICAgICAgICAgICAhPSBvdGhlci5nZXRPbmVvZkludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIGlmICghZ2V0T25lb2ZTdWJtZXNzYWdlKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mU3VibWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgaWYgKCFnZXRPbmVvZlN0cmluZygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZlN0cmluZygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA0OgogICAgICAgICAgaWYgKCFnZXRPbmVvZkJ5dGVzKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mQnl0ZXMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNToKICAgICAgICAgIGlmICghZ2V0T25lb2ZTdHJpbmdDb3JkKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mU3RyaW5nQ29yZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA2OgogICAgICAgICAgaWYgKCFnZXRPbmVvZkJ5dGVzQ29yZCgpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZkJ5dGVzQ29yZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA3OgogICAgICAgICAgaWYgKCFnZXRPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mU3RyaW5nU3RyaW5nUGllY2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgODoKICAgICAgICAgIGlmICghZ2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mQnl0ZXNTdHJpbmdQaWVjZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA5OgogICAgICAgICAgaWYgKCFnZXRPbmVvZkVudW0oKQogICAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T25lb2ZFbnVtKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDA6CiAgICAgICAgZGVmYXVsdDoKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIHN3aXRjaCAob25lb2ZGaWVsZENhc2VfKSB7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZJbnQzMigpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfU1VCTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZlN1Ym1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfU1RSSU5HX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9uZW9mU3RyaW5nKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNDoKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX0JZVEVTX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9uZW9mQnl0ZXMoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1OgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfU1RSSU5HX0NPUkRfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZTdHJpbmdDb3JkKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNjoKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX0JZVEVTX0NPUkRfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZCeXRlc0NvcmQoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA3OgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfU1RSSU5HX1NUUklOR19QSUVDRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgODoKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX0JZVEVTX1NUUklOR19QSUVDRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZkJ5dGVzU3RyaW5nUGllY2UoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA5OgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZkVudW0oKS5nZXROdW1iZXIoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMDoKICAgICAgICBkZWZhdWx0OgogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0T25lb2ZQYXJzaW5nTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0T25lb2ZQYXJzaW5nTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RPbmVvZlBhcnNpbmdMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE9uZW9mUGFyc2luZ0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmIChvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgYnVpbGRQYXJ0aWFsT25lb2ZzKHJlc3VsdCk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsT25lb2ZzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHJlc3VsdCkgewogICAgICAgIHJlc3VsdC5vbmVvZkZpZWxkQ2FzZV8gPSBvbmVvZkZpZWxkQ2FzZV87CiAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRfID0gdGhpcy5vbmVvZkZpZWxkXzsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIgJiYKICAgICAgICAgICAgb25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRfID0gb25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIHN3aXRjaCAob3RoZXIuZ2V0T25lb2ZGaWVsZENhc2UoKSkgewogICAgICAgICAgY2FzZSBPTkVPRl9JTlQzMjogewogICAgICAgICAgICBzZXRPbmVvZkludDMyKG90aGVyLmdldE9uZW9mSW50MzIoKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9TVUJNRVNTQUdFOiB7CiAgICAgICAgICAgIG1lcmdlT25lb2ZTdWJtZXNzYWdlKG90aGVyLmdldE9uZW9mU3VibWVzc2FnZSgpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX1NUUklORzogewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAzOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG90aGVyLm9uZW9mRmllbGRfOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX0JZVEVTOiB7CiAgICAgICAgICAgIHNldE9uZW9mQnl0ZXMob3RoZXIuZ2V0T25lb2ZCeXRlcygpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX1NUUklOR19DT1JEOiB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDU7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gb3RoZXIub25lb2ZGaWVsZF87CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfQllURVNfQ09SRDogewogICAgICAgICAgICBzZXRPbmVvZkJ5dGVzQ29yZChvdGhlci5nZXRPbmVvZkJ5dGVzQ29yZCgpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX1NUUklOR19TVFJJTkdfUElFQ0U6IHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNzsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBvdGhlci5vbmVvZkZpZWxkXzsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9CWVRFU19TVFJJTkdfUElFQ0U6IHsKICAgICAgICAgICAgc2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKG90aGVyLmdldE9uZW9mQnl0ZXNTdHJpbmdQaWVjZSgpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX0VOVU06IHsKICAgICAgICAgICAgc2V0T25lb2ZFbnVtKG90aGVyLmdldE9uZW9mRW51bSgpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GRklFTERfTk9UX1NFVDogewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4CiAgICAgICAgICAgICAgY2FzZSAxODogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0T25lb2ZTdWJtZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTgKICAgICAgICAgICAgICBjYXNlIDI2OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDM7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGJzOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI2CiAgICAgICAgICAgICAgY2FzZSAzNDogewogICAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDQ7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzQKICAgICAgICAgICAgICBjYXNlIDQyOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDU7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGJzOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQyCiAgICAgICAgICAgICAgY2FzZSA1MDogewogICAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDY7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTAKICAgICAgICAgICAgICBjYXNlIDU4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDc7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGJzOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDU4CiAgICAgICAgICAgICAgY2FzZSA2NjogewogICAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNjYKICAgICAgICAgICAgICBjYXNlIDcyOiB7CiAgICAgICAgICAgICAgICBpbnQgcmF3VmFsdWUgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSB2YWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZS5mb3JOdW1iZXIocmF3VmFsdWUpOwogICAgICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoOSwgcmF3VmFsdWUpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gOTsKICAgICAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSByYXdWYWx1ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3MgogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBvbmVvZkZpZWxkXzsKICAgICAgcHVibGljIE9uZW9mRmllbGRDYXNlCiAgICAgICAgICBnZXRPbmVvZkZpZWxkQ2FzZSgpIHsKICAgICAgICByZXR1cm4gT25lb2ZGaWVsZENhc2UuZm9yTnVtYmVyKAogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8pOwogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mRmllbGQoKSB7CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAvKioKICAgICAgICogPGNvZGU+aW50MzIgb25lb2ZfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkludDMyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mSW50MzIoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5pbnQzMiBvbmVvZl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRPbmVvZkludDMyKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMSkgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIHJldHVybiAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5pbnQzMiBvbmVvZl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mSW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZkludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxOwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmludDMyIG9uZW9mX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZJbnQzMigpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDEpIHsKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gb25lb2ZTdWJtZXNzYWdlQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2Zfc3VibWVzc2FnZSA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3VibWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3VibWVzc2FnZSgpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3VibWVzc2FnZS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T25lb2ZTdWJtZXNzYWdlKCkgewogICAgICAgIGlmIChvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXzsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgICAgcmV0dXJuIG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mU3VibWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mU3VibWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT25lb2ZTdWJtZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAyICYmCiAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUubmV3QnVpbGRlcigoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF8pCiAgICAgICAgICAgICAgICAubWVyZ2VGcm9tKHZhbHVlKS5idWlsZFBhcnRpYWwoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAyKSB7CiAgICAgICAgICAgIG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZTdWJtZXNzYWdlKCkgewogICAgICAgIGlmIChvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAyKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2Zfc3VibWVzc2FnZSA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRPbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBnZXRPbmVvZlN1Ym1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9uZW9mU3VibWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgICBpZiAoKG9uZW9mRmllbGRDYXNlXyA9PSAyKSAmJiAob25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkpIHsKICAgICAgICAgIHJldHVybiBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMikgewogICAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2Zfc3VibWVzc2FnZSA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9uZW9mU3VibWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCEob25lb2ZGaWVsZENhc2VfID09IDIpKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXzsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAzOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmcoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDMpIHsKICAgICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0KICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMykgewogICAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gczsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldE9uZW9mU3RyaW5nQnl0ZXMoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDMpIHsKICAgICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICBpZiAocmVmIGluc3RhbmNlb2YgU3RyaW5nKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYjsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAzOwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlN0cmluZygpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDMpIHsKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN0cmluZ0J5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAzOwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDQgW2RlZmF1bHQgPSAiZGVmYXVsdCBieXRlcyJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mQnl0ZXMoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDQgW2RlZmF1bHQgPSAiZGVmYXVsdCBieXRlcyJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlcy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlcygpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDQpIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoImRlZmF1bHQgYnl0ZXMiKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA0IFtkZWZhdWx0ID0gImRlZmF1bHQgYnl0ZXMiXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZCeXRlcyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mQnl0ZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA0OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNCBbZGVmYXVsdCA9ICJkZWZhdWx0IGJ5dGVzIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mQnl0ZXMoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA0KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19jb3JkID0gNSBbZGVmYXVsdCA9ICJkZWZhdWx0IENvcmQiLCBjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZ0NvcmQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlN0cmluZ0NvcmQoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA1OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX2NvcmQgPSA1IFtkZWZhdWx0ID0gImRlZmF1bHQgQ29yZCIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZ0NvcmQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE9uZW9mU3RyaW5nQ29yZCgpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICJkZWZhdWx0IENvcmQiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIGlmICghKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPQogICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1KSB7CiAgICAgICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBzOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX2NvcmQgPSA1IFtkZWZhdWx0ID0gImRlZmF1bHQgQ29yZCIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdDb3JkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXRPbmVvZlN0cmluZ0NvcmRCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICJkZWZhdWx0IENvcmQiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBTdHJpbmcpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBiOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX2NvcmQgPSA1IFtkZWZhdWx0ID0gImRlZmF1bHQgQ29yZCIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mU3RyaW5nQ29yZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mU3RyaW5nQ29yZCgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDU7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19jb3JkID0gNSBbZGVmYXVsdCA9ICJkZWZhdWx0IENvcmQiLCBjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlN0cmluZ0NvcmQoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX2NvcmQgPSA1IFtkZWZhdWx0ID0gImRlZmF1bHQgQ29yZCIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZ0NvcmQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN0cmluZ0NvcmRCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTsKICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mQnl0ZXNDb3JkIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mQnl0ZXNDb3JkKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNjsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzQ29yZC4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlc0NvcmQoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA2KSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzX2NvcmQgPSA2IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvbmVvZkJ5dGVzQ29yZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mQnl0ZXNDb3JkKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNjsKICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19jb3JkID0gNiBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZCeXRlc0NvcmQoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA2KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nU3RyaW5nUGllY2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gIiI7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDcpIHsKICAgICAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IHM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfc3RyaW5nX3BpZWNlID0gNyBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nU3RyaW5nUGllY2UuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldE9uZW9mU3RyaW5nU3RyaW5nUGllY2VCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNykgewogICAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBTdHJpbmcpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDcpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBiOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZTdHJpbmdTdHJpbmdQaWVjZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mU3RyaW5nU3RyaW5nUGllY2UoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA3OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfc3RyaW5nX3BpZWNlID0gNyBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNykgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZUJ5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA3OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19zdHJpbmdfcGllY2UgPSA4IFtkZWZhdWx0ID0gImRlZmF1bHQgU3RyaW5nUGllY2UiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mQnl0ZXNTdHJpbmdQaWVjZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzU3RyaW5nUGllY2UoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA4OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19zdHJpbmdfcGllY2UgPSA4IFtkZWZhdWx0ID0gImRlZmF1bHQgU3RyaW5nUGllY2UiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzU3RyaW5nUGllY2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXNTdHJpbmdQaWVjZSgpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDgpIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoImRlZmF1bHQgU3RyaW5nUGllY2UiKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfc3RyaW5nX3BpZWNlID0gOCBbZGVmYXVsdCA9ICJkZWZhdWx0IFN0cmluZ1BpZWNlIiwgY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvbmVvZkJ5dGVzU3RyaW5nUGllY2UgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZkJ5dGVzU3RyaW5nUGllY2UoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA4OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzX3N0cmluZ19waWVjZSA9IDggW2RlZmF1bHQgPSAiZGVmYXVsdCBTdHJpbmdQaWVjZSIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gOCkgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVjJFbnVtTGl0ZSBvbmVvZl9lbnVtID0gOTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZFbnVtIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZFbnVtKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gOTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5WMkVudW1MaXRlIG9uZW9mX2VudW0gPSA5OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZFbnVtLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSBnZXRPbmVvZkVudW0oKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA5KSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuZm9yTnVtYmVyKAogICAgICAgICAgICAgIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF8pOwogICAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZS5WMl9GSVJTVCA6IHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuVjJfRklSU1Q7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90bzJfdW5pdHRlc3QuVjJFbnVtTGl0ZSBvbmVvZl9lbnVtID0gOTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZFbnVtIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZFbnVtKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDk7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZS5nZXROdW1iZXIoKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvMl91bml0dGVzdC5WMkVudW1MaXRlIG9uZW9mX2VudW0gPSA5OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkVudW0oKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA5KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0T25lb2ZQYXJzaW5nTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RPbmVvZlBhcnNpbmdMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE9uZW9mUGFyc2luZ0xpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdE9uZW9mUGFyc2luZ0xpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RPbmVvZlBhcnNpbmdMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RPbmVvZlBhcnNpbmdMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RNZXNzYWdlU2V0TGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuVGVzdE1lc3NhZ2VTZXRMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy4KICAgICAgICAgIEV4dGVuZGFibGVNZXNzYWdlT3JCdWlsZGVyPFRlc3RNZXNzYWdlU2V0TGl0ZT4gewogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdE1lc3NhZ2VTZXRMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdE1lc3NhZ2VTZXRMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZU1lc3NhZ2U8CiAgICAgICAgVGVzdE1lc3NhZ2VTZXRMaXRlPiBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXNzYWdlU2V0TGl0ZSkKICAgICAgVGVzdE1lc3NhZ2VTZXRMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0TWVzc2FnZVNldExpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdE1lc3NhZ2VTZXRMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSwgPz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdE1lc3NhZ2VTZXRMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RNZXNzYWdlU2V0TGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VTZXRMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVzc2FnZVNldExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBpZiAoIWV4dGVuc2lvbnNBcmVJbml0aWFsaXplZCgpKSB7CiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5FeHRlbmRhYmxlTWVzc2FnZTxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGU+LkV4dGVuc2lvbldyaXRlcgogICAgICAgICAgZXh0ZW5zaW9uV3JpdGVyID0gbmV3TWVzc2FnZVNldEV4dGVuc2lvbldyaXRlcigpOwogICAgICBleHRlbnNpb25Xcml0ZXIud3JpdGVVbnRpbCgyMTQ3NDgzNjQ3LCBvdXRwdXQpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVBc01lc3NhZ2VTZXRUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgc2l6ZSArPSBleHRlbnNpb25zU2VyaWFsaXplZFNpemVBc01lc3NhZ2VTZXQoKTsKICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemVBc01lc3NhZ2VTZXQoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlKSBvYmo7CgogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldEV4dGVuc2lvbkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRFeHRlbnNpb25GaWVsZHMoKSkpCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGhhc2ggPSBoYXNoRmllbGRzKGhhc2gsIGdldEV4dGVuc2lvbkZpZWxkcygpKTsKICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0TWVzc2FnZVNldExpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUsIEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0TWVzc2FnZVNldExpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VTZXRMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VTZXRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVzc2FnZVNldExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUodGhpcyk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSwgVHlwZT4gZXh0ZW5zaW9uLAogICAgICAgICAgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRFeHRlbnNpb24oZXh0ZW5zaW9uLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgc2V0RXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUsIGphdmEudXRpbC5MaXN0PFR5cGU+PiBleHRlbnNpb24sCiAgICAgICAgICBpbnQgaW5kZXgsIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RXh0ZW5zaW9uKGV4dGVuc2lvbiwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBhZGRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkRXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUPiBCdWlsZGVyIGNsZWFyRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUsIFQ+IGV4dGVuc2lvbikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckV4dGVuc2lvbihleHRlbnNpb24pOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIHRoaXMubWVyZ2VFeHRlbnNpb25GaWVsZHMob3RoZXIpOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBpZiAoIWV4dGVuc2lvbnNBcmVJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXNzYWdlU2V0TGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXNzYWdlU2V0TGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RNZXNzYWdlU2V0TGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0TWVzc2FnZVNldExpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0TWVzc2FnZVNldExpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWVzc2FnZVNldExpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE1lc3NhZ2VTZXRMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBQYWNrZWRJbnQzMk9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuUGFja2VkSW50MzIpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRSZXBlYXRlZEludDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRJbnQzMihpbnQgaW5kZXgpOwogIH0KICAvKioKICAgKiA8cHJlPgogICAqIFRoZSBmb2xsb3dpbmcgZm91ciBtZXNzYWdlcyBhcmUgc2V0IHVwIHRvIHRlc3QgZm9yIHdpcmUgY29tcGF0aWJpbGl0eSBiZXR3ZWVuCiAgICogcGFja2VkIGFuZCBub24tcGFja2VkIHJlcGVhdGVkIGZpZWxkcy4gV2UgdXNlIHRoZSBmaWVsZCBudW1iZXIgMjA0OCwgYmVjYXVzZQogICAqIHRoYXQgaXMgbGFyZ2UgZW5vdWdoIHRvIHJlcXVpcmUgYSAzLWJ5dGUgdmFyaW50IGZvciB0aGUgdGFnLgogICAqIDwvcHJlPgogICAqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlBhY2tlZEludDMyfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgUGFja2VkSW50MzIgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlBhY2tlZEludDMyKQogICAgICBQYWNrZWRJbnQzMk9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgUGFja2VkSW50MzIubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgUGFja2VkSW50MzIoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBQYWNrZWRJbnQzMigpIHsKICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBQYWNrZWRJbnQzMigpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkSW50MzJfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1BhY2tlZEludDMyX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDIwNDg7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkSW50MzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEludDMyLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50MzJDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50MzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcmVwZWF0ZWRJbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEludDMyTGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZygxNjM4Nik7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocmVwZWF0ZWRJbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMk5vVGFnKHJlcGVhdGVkSW50MzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhyZXBlYXRlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMzsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICByZXBlYXRlZEludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMikgb2JqOwoKICAgICAgaWYgKCFnZXRSZXBlYXRlZEludDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkSW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGdldFJlcGVhdGVkSW50MzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZEludDMyTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRoZSBmb2xsb3dpbmcgZm91ciBtZXNzYWdlcyBhcmUgc2V0IHVwIHRvIHRlc3QgZm9yIHdpcmUgY29tcGF0aWJpbGl0eSBiZXR3ZWVuCiAgICAgKiBwYWNrZWQgYW5kIG5vbi1wYWNrZWQgcmVwZWF0ZWQgZmllbGRzLiBXZSB1c2UgdGhlIGZpZWxkIG51bWJlciAyMDQ4LCBiZWNhdXNlCiAgICAgKiB0aGF0IGlzIGxhcmdlIGVub3VnaCB0byByZXF1aXJlIGEgMy1ieXRlIHZhcmludCBmb3IgdGhlIHRhZy4KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5QYWNrZWRJbnQzMn0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5QYWNrZWRJbnQzMikKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMk9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1BhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkSW50MzJfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkSW50MzJfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMih0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkSW50MzJfID0gcmVwZWF0ZWRJbnQzMl87CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEludDMyXyA9IG90aGVyLnJlcGVhdGVkSW50MzJfOwogICAgICAgICAgICByZXBlYXRlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkQWxsKG90aGVyLnJlcGVhdGVkSW50MzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDE2Mzg0OiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2Mzg0CiAgICAgICAgICAgICAgY2FzZSAxNjM4NjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludChpbnB1dC5yZWFkSW50MzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYzODYKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEludDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRJbnQzMl8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZEludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkSW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEludDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkSW50MzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRJbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkSW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEludDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkSW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEludDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZEludDMyXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEludDMyKCkgewogICAgICAgIHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5QYWNrZWRJbnQzMikKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlBhY2tlZEludDMyKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UGFja2VkSW50MzI+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UGFja2VkSW50MzI+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBQYWNrZWRJbnQzMiBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFBhY2tlZEludDMyPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFBhY2tlZEludDMyPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIE5vblBhY2tlZEludDMyT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5Ob25QYWNrZWRJbnQzMikKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5Ob25QYWNrZWRJbnQzMn0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIE5vblBhY2tlZEludDMyIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5Ob25QYWNrZWRJbnQzMikKICAgICAgTm9uUGFja2VkSW50MzJPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIE5vblBhY2tlZEludDMyLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIE5vblBhY2tlZEludDMyKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgTm9uUGFja2VkSW50MzIoKSB7CiAgICAgIHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgTm9uUGFja2VkSW50MzIoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Ob25QYWNrZWRJbnQzMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMi5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9JTlQzMl9GSUVMRF9OVU1CRVIgPSAyMDQ4OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEludDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigyMDQ4LCByZXBlYXRlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkSW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcocmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDMgKiBnZXRSZXBlYXRlZEludDMyTGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMikpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIpIG9iajsKCiAgICAgIGlmICghZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEludDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEludDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5Ob25QYWNrZWRJbnQzMn0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5Ob25QYWNrZWRJbnQzMikKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMk9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkSW50MzJfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkSW50MzJfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMih0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkSW50MzJfID0gcmVwZWF0ZWRJbnQzMl87CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEludDMyXyA9IG90aGVyLnJlcGVhdGVkSW50MzJfOwogICAgICAgICAgICByZXBlYXRlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkQWxsKG90aGVyLnJlcGVhdGVkSW50MzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDE2Mzg0OiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2Mzg0CiAgICAgICAgICAgICAgY2FzZSAxNjM4NjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludChpbnB1dC5yZWFkSW50MzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYzODYKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEludDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRJbnQzMl8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRSZXBlYXRlZEludDMyTGlzdCgpIHsKICAgICAgICByZXBlYXRlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRJbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW50MzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkSW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkSW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEludDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZEludDMyXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkSW50MzIoKSB7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0Lk5vblBhY2tlZEludDMyKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuTm9uUGFja2VkSW50MzIpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMigpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOb25QYWNrZWRJbnQzMj4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxOb25QYWNrZWRJbnQzMj4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIE5vblBhY2tlZEludDMyIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8Tm9uUGFja2VkSW50MzI+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8Tm9uUGFja2VkSW50MzI+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgUGFja2VkRml4ZWQzMk9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuUGFja2VkRml4ZWQzMikKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQzMi4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyKGludCBpbmRleCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5QYWNrZWRGaXhlZDMyfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgUGFja2VkRml4ZWQzMiBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuUGFja2VkRml4ZWQzMikKICAgICAgUGFja2VkRml4ZWQzMk9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgUGFja2VkRml4ZWQzMi5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBQYWNrZWRGaXhlZDMyKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgUGFja2VkRml4ZWQzMigpIHsKICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFBhY2tlZEZpeGVkMzIoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1BhY2tlZEZpeGVkMzJfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1BhY2tlZEZpeGVkMzJfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0ZJWEVEMzJfRklFTERfTlVNQkVSID0gMjA0ODsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRGaXhlZDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHJlcGVhdGVkRml4ZWQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDE2Mzg2KTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhyZXBlYXRlZEZpeGVkMzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkRml4ZWQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVGaXhlZDMyTm9UYWcocmVwZWF0ZWRGaXhlZDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDQgKiBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDM7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMikgb2JqOwoKICAgICAgaWYgKCFnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlBhY2tlZEZpeGVkMzJ9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuUGFja2VkRml4ZWQzMikKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1BhY2tlZEZpeGVkMzJfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMi5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9QYWNrZWRGaXhlZDMyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMi5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMih0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEZpeGVkMzJfID0gcmVwZWF0ZWRGaXhlZDMyXzsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMi5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEZpeGVkMzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkRml4ZWQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBvdGhlci5yZXBlYXRlZEZpeGVkMzJfOwogICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8uYWRkQWxsKG90aGVyLnJlcGVhdGVkRml4ZWQzMl8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTYzODk6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZEZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYzODkKICAgICAgICAgICAgICBjYXNlIDE2Mzg2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKGFsbG9jIC8gNCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8uYWRkSW50KGlucHV0LnJlYWRGaXhlZDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2Mzg2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkRml4ZWQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRGaXhlZDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKGludCBjYXBhY2l0eSkgewogICAgICAgIGlmICghcmVwZWF0ZWRGaXhlZDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZEZpeGVkMzJfLCBjYXBhY2l0eSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZpeGVkMzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkgewogICAgICAgIHJlcGVhdGVkRml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRml4ZWQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZpeGVkMzIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRGaXhlZDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaXhlZDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEZpeGVkMzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpeGVkMzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkRml4ZWQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWRGaXhlZDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRGaXhlZDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkRml4ZWQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkRml4ZWQzMigpIHsKICAgICAgICByZXBlYXRlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5QYWNrZWRGaXhlZDMyKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuUGFja2VkRml4ZWQzMikKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMigpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFBhY2tlZEZpeGVkMzI+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UGFja2VkRml4ZWQzMj4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFBhY2tlZEZpeGVkMzIgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxQYWNrZWRGaXhlZDMyPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFBhY2tlZEZpeGVkMzI+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBOb25QYWNrZWRGaXhlZDMyT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5Ob25QYWNrZWRGaXhlZDMyKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEZpeGVkMzIoaW50IGluZGV4KTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0Lk5vblBhY2tlZEZpeGVkMzJ9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBOb25QYWNrZWRGaXhlZDMyIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5Ob25QYWNrZWRGaXhlZDMyKQogICAgICBOb25QYWNrZWRGaXhlZDMyT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBOb25QYWNrZWRGaXhlZDMyLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIE5vblBhY2tlZEZpeGVkMzIoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBOb25QYWNrZWRGaXhlZDMyKCkgewogICAgICByZXBlYXRlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgTm9uUGFja2VkRml4ZWQzMigpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRklYRUQzMl9GSUVMRF9OVU1CRVIgPSAyMDQ4OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEZpeGVkMzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRml4ZWQzMigyMDQ4LCByZXBlYXRlZEZpeGVkMzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gNCAqIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDMgKiBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMikgb2JqOwoKICAgICAgaWYgKCFnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0Lk5vblBhY2tlZEZpeGVkMzJ9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuTm9uUGFja2VkRml4ZWQzMikKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X05vblBhY2tlZEZpeGVkMzJfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMi5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Ob25QYWNrZWRGaXhlZDMyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMi5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMih0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEZpeGVkMzJfID0gcmVwZWF0ZWRGaXhlZDMyXzsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMi5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEZpeGVkMzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkRml4ZWQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBvdGhlci5yZXBlYXRlZEZpeGVkMzJfOwogICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8uYWRkQWxsKG90aGVyLnJlcGVhdGVkRml4ZWQzMl8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTYzODk6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZEZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYzODkKICAgICAgICAgICAgICBjYXNlIDE2Mzg2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKGFsbG9jIC8gNCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8uYWRkSW50KGlucHV0LnJlYWRGaXhlZDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2Mzg2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkRml4ZWQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRGaXhlZDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKGludCBjYXBhY2l0eSkgewogICAgICAgIGlmICghcmVwZWF0ZWRGaXhlZDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZEZpeGVkMzJfLCBjYXBhY2l0eSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkMzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRml4ZWQzMkNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZpeGVkMzIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEZpeGVkMzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpeGVkMzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEZpeGVkMzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRGaXhlZDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaXhlZDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWRGaXhlZDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRGaXhlZDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkRml4ZWQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRGaXhlZDMyKCkgewogICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0Lk5vblBhY2tlZEZpeGVkMzIpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5Ob25QYWNrZWRGaXhlZDMyKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8Tm9uUGFja2VkRml4ZWQzMj4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxOb25QYWNrZWRGaXhlZDMyPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgTm9uUGFja2VkRml4ZWQzMiBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE5vblBhY2tlZEZpeGVkMzI+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8Tm9uUGFja2VkRml4ZWQzMj4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIER1cEVudW1PckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LkR1cEVudW0pCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CiAgfQogIC8qKgogICAqIDxwcmU+CiAgICogVGVzdCBhbiBlbnVtIHRoYXQgaGFzIG11bHRpcGxlIHZhbHVlcyB3aXRoIHRoZSBzYW1lIG51bWJlci4KICAgKiA8L3ByZT4KICAgKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5EdXBFbnVtfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgRHVwRW51bSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuRHVwRW51bSkKICAgICAgRHVwRW51bU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgRHVwRW51bS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBEdXBFbnVtKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgRHVwRW51bSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBEdXBFbnVtKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9EdXBFbnVtX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9EdXBFbnVtX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICAvKioKICAgICAqIFByb3RvYnVmIGVudW0ge0Bjb2RlIHByb3RvMl91bml0dGVzdC5EdXBFbnVtLlRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZX0KICAgICAqLwogICAgcHVibGljIGVudW0gVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlCiAgICAgICAgaW1wbGVtZW50cyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sTWVzc2FnZUVudW0gewogICAgICAvKioKICAgICAgICogPGNvZGU+Rk9PMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgRk9PMSgxKSwKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkJBUjEgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEJBUjEoMiksCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5CQVogPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIEJBWigzKSwKICAgICAgOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkZPTzIgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlIEZPTzIgPSBGT08xOwogICAgICAvKioKICAgICAgICogPGNvZGU+QkFSMiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGUgQkFSMiA9IEJBUjE7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5GT08xID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBGT08xX1ZBTFVFID0gMTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkJBUjEgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEJBUjFfVkFMVUUgPSAyOwogICAgICAvKioKICAgICAgICogPGNvZGU+QkFaID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBCQVpfVkFMVUUgPSAzOwogICAgICAvKioKICAgICAgICogPGNvZGU+Rk9PMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRk9PMl9WQUxVRSA9IDE7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5CQVIyID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBCQVIyX1ZBTFVFID0gMjsKCgogICAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgc3RhdGljIFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZSB2YWx1ZU9mKGludCB2YWx1ZSkgewogICAgICAgIHJldHVybiBmb3JOdW1iZXIodmFsdWUpOwogICAgICB9CgogICAgICAvKioKICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgICBzd2l0Y2ggKHZhbHVlKSB7CiAgICAgICAgICBjYXNlIDE6IHJldHVybiBGT08xOwogICAgICAgICAgY2FzZSAyOiByZXR1cm4gQkFSMTsKICAgICAgICAgIGNhc2UgMzogcmV0dXJuIEJBWjsKICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZT4KICAgICAgICAgIGludGVybmFsR2V0VmFsdWVNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsVmFsdWVNYXA7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDwKICAgICAgICAgIFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZT4gaW50ZXJuYWxWYWx1ZU1hcCA9CiAgICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZT4oKSB7CiAgICAgICAgICAgICAgcHVibGljIFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZSBmaW5kVmFsdWVCeU51bWJlcihpbnQgbnVtYmVyKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlLmZvck51bWJlcihudW1iZXIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfTsKCiAgICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IKICAgICAgICAgIGdldFZhbHVlRGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpLmdldFZhbHVlcygpLmdldChvcmRpbmFsKCkpOwogICAgICB9CiAgICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5nZXREZXNjcmlwdG9yKCkuZ2V0RW51bVR5cGVzKCkuZ2V0KDApOwogICAgICB9CgogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGVbXSBWQUxVRVMgPSBnZXRTdGF0aWNWYWx1ZXNBcnJheSgpOwogICAgICBwcml2YXRlIHN0YXRpYyBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGVbXSBnZXRTdGF0aWNWYWx1ZXNBcnJheSgpIHsKICAgICAgICByZXR1cm4gbmV3IFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZVtdIHsKICAgICAgICBGT08xLCBCQVIxLCBCQVosIEZPTzIsIEJBUjIsIAogICAgICAgIH07CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGUgdmFsdWVPZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvciBkZXNjKSB7CiAgICAgICAgaWYgKGRlc2MuZ2V0VHlwZSgpICE9IGdldERlc2NyaXB0b3IoKSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAgICJFbnVtVmFsdWVEZXNjcmlwdG9yIGlzIG5vdCBmb3IgdGhpcyB0eXBlLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gVkFMVUVTW2Rlc2MuZ2V0SW5kZXgoKV07CiAgICAgIH0KCiAgICAgIHByaXZhdGUgZmluYWwgaW50IHZhbHVlOwoKICAgICAgcHJpdmF0ZSBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGUoaW50IHZhbHVlKSB7CiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgICB9CgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90bzJfdW5pdHRlc3QuRHVwRW51bS5UZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGUpCiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtKSBvYmo7CgogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRlc3QgYW4gZW51bSB0aGF0IGhhcyBtdWx0aXBsZSB2YWx1ZXMgd2l0aCB0aGUgc2FtZSBudW1iZXIuCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuRHVwRW51bX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5EdXBFbnVtKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW1PckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9EdXBFbnVtX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRHVwRW51bV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRHVwRW51bV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0uZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0odGhpcyk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LkR1cEVudW0pCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5EdXBFbnVtKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8RHVwRW51bT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxEdXBFbnVtPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgRHVwRW51bSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPER1cEVudW0+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8RHVwRW51bT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFJlY3Vyc2l2ZU1lc3NhZ2VPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSByZWN1cnNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNSZWN1cnNlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSByZWN1cnNlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIGdldFJlY3Vyc2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlIHJlY3Vyc2UgPSAxOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZU9yQnVpbGRlciBnZXRSZWN1cnNlT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBwYXlsb2FkID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIHBheWxvYWQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc1BheWxvYWQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgcGF5bG9hZCA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgcGF5bG9hZC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldFBheWxvYWQoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2V9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBSZWN1cnNpdmVNZXNzYWdlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlKQogICAgICBSZWN1cnNpdmVNZXNzYWdlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBSZWN1cnNpdmVNZXNzYWdlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFJlY3Vyc2l2ZU1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBSZWN1cnNpdmVNZXNzYWdlKCkgewogICAgICBwYXlsb2FkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBSZWN1cnNpdmVNZXNzYWdlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVDVVJTRV9GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHJlY3Vyc2VfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSByZWN1cnNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzUmVjdXJzZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgcmVjdXJzZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgZ2V0UmVjdXJzZSgpIHsKICAgICAgcmV0dXJuIHJlY3Vyc2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVjdXJzZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlT3JCdWlsZGVyIGdldFJlY3Vyc2VPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiByZWN1cnNlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlY3Vyc2VfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBWUxPQURfRklFTERfTlVNQkVSID0gMjsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHBheWxvYWRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBwYXlsb2FkID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIHBheWxvYWQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNQYXlsb2FkKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIHBheWxvYWQgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIHBheWxvYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0UGF5bG9hZCgpIHsKICAgICAgcmV0dXJuIHBheWxvYWRfOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxLCBnZXRSZWN1cnNlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUJ5dGVzKDIsIHBheWxvYWRfKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEsIGdldFJlY3Vyc2UoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUJ5dGVzU2l6ZSgyLCBwYXlsb2FkXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlKSBvYmo7CgogICAgICBpZiAoaGFzUmVjdXJzZSgpICE9IG90aGVyLmhhc1JlY3Vyc2UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzUmVjdXJzZSgpKSB7CiAgICAgICAgaWYgKCFnZXRSZWN1cnNlKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZWN1cnNlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc1BheWxvYWQoKSAhPSBvdGhlci5oYXNQYXlsb2FkKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc1BheWxvYWQoKSkgewogICAgICAgIGlmICghZ2V0UGF5bG9hZCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGF5bG9hZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc1JlY3Vyc2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFQ1VSU0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlY3Vyc2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNQYXlsb2FkKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQVlMT0FEX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYXlsb2FkKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1JlY3Vyc2l2ZU1lc3NhZ2VfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCkgewogICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMpIHsKICAgICAgICAgIGdldFJlY3Vyc2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIHJlY3Vyc2VfID0gbnVsbDsKICAgICAgICBpZiAocmVjdXJzZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJlY3Vyc2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICByZWN1cnNlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBwYXlsb2FkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LnJlY3Vyc2VfID0gcmVjdXJzZUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IHJlY3Vyc2VfCiAgICAgICAgICAgICAgOiByZWN1cnNlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5wYXlsb2FkXyA9IHBheWxvYWRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNSZWN1cnNlKCkpIHsKICAgICAgICAgIG1lcmdlUmVjdXJzZShvdGhlci5nZXRSZWN1cnNlKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzUGF5bG9hZCgpKSB7CiAgICAgICAgICBzZXRQYXlsb2FkKG90aGVyLmdldFBheWxvYWQoKSk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTA6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldFJlY3Vyc2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEwCiAgICAgICAgICAgICAgY2FzZSAxODogewogICAgICAgICAgICAgICAgcGF5bG9hZF8gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxOAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZU9yQnVpbGRlcj4gcmVjdXJzZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlIHJlY3Vyc2UgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSByZWN1cnNlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc1JlY3Vyc2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSByZWN1cnNlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgZ2V0UmVjdXJzZSgpIHsKICAgICAgICBpZiAocmVjdXJzZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZWN1cnNlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlY3Vyc2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVjdXJzZUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZWN1cnNlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAocmVjdXJzZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgcmVjdXJzZV8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVjdXJzZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZWN1cnNlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZWN1cnNlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVjdXJzZV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVjdXJzZUJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZVJlY3Vyc2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChyZWN1cnNlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApICYmCiAgICAgICAgICAgIHJlY3Vyc2VfICE9IG51bGwgJiYKICAgICAgICAgICAgcmVjdXJzZV8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRSZWN1cnNlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZWN1cnNlXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZWN1cnNlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJlY3Vyc2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvMl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlIHJlY3Vyc2UgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVjdXJzZSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgcmVjdXJzZV8gPSBudWxsOwogICAgICAgIGlmIChyZWN1cnNlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmVjdXJzZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIHJlY3Vyc2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuQnVpbGRlciBnZXRSZWN1cnNlQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldFJlY3Vyc2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90bzJfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZU9yQnVpbGRlciBnZXRSZWN1cnNlT3JCdWlsZGVyKCkgewogICAgICAgIGlmIChyZWN1cnNlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlY3Vyc2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZWN1cnNlXyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVjdXJzZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG8yX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldFJlY3Vyc2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKHJlY3Vyc2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZWN1cnNlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2VPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRSZWN1cnNlKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICByZWN1cnNlXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZWN1cnNlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHBheWxvYWRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgcGF5bG9hZCA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIHBheWxvYWQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNQYXlsb2FkKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgcGF5bG9hZCA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBwYXlsb2FkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldFBheWxvYWQoKSB7CiAgICAgICAgcmV0dXJuIHBheWxvYWRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBwYXlsb2FkID0gMjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGF5bG9hZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBheWxvYWQoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBwYXlsb2FkXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgcGF5bG9hZCA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBheWxvYWQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgIHBheWxvYWRfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0UGF5bG9hZCgpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlY3Vyc2l2ZU1lc3NhZ2U+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UmVjdXJzaXZlTWVzc2FnZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFJlY3Vyc2l2ZU1lc3NhZ2UgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZWN1cnNpdmVNZXNzYWdlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlY3Vyc2l2ZU1lc3NhZ2U+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfSU5UMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTsKICAvKioKICAgKiA8cHJlPgogICAqIFNpbmd1bGFyCiAgICogPC9wcmU+CiAgICoKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5JbnRlZ2VyPiBvcHRpb25hbEludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfSU5UNjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5Mb25nPiBvcHRpb25hbEludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfVUlOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDM7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gb3B0aW9uYWxVaW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9VSU5UNjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5Mb25nPiBvcHRpb25hbFVpbnQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NJTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA1OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkludGVnZXI+IG9wdGlvbmFsU2ludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfU0lOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDY7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gb3B0aW9uYWxTaW50NjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9GSVhFRDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDc7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gb3B0aW9uYWxGaXhlZDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfRklYRUQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA4OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkxvbmc+IG9wdGlvbmFsRml4ZWQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NGSVhFRDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDk7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gb3B0aW9uYWxTZml4ZWQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NGSVhFRDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDEwOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkxvbmc+IG9wdGlvbmFsU2ZpeGVkNjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9GTE9BVF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5GbG9hdD4gb3B0aW9uYWxGbG9hdEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5GbG9hdC5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9ET1VCTEVfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTI7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuRG91YmxlPiBvcHRpb25hbERvdWJsZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Eb3VibGUuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfQk9PTF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5Cb29sZWFuPiBvcHRpb25hbEJvb2xFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuQm9vbGVhbi5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9TVFJJTkdfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTQ7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuU3RyaW5nPiBvcHRpb25hbFN0cmluZ0V4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfQllURVNfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTU7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG9wdGlvbmFsQnl0ZXNFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxHUk9VUF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxNjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGU+IG9wdGlvbmFsR3JvdXBFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlLmNsYXNzLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX05FU1RFRF9NRVNTQUdFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDE4OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9GT1JFSUdOX01FU1NBR0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTk7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9JTVBPUlRfTUVTU0FHRV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAyMDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlPiBvcHRpb25hbEltcG9ydE1lc3NhZ2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfTkVTVEVEX0VOVU1fRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjE7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+IG9wdGlvbmFsTmVzdGVkRW51bUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9GT1JFSUdOX0VOVU1fRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjI7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IG9wdGlvbmFsRm9yZWlnbkVudW1FeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfSU1QT1JUX0VOVU1fRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjM7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4gb3B0aW9uYWxJbXBvcnRFbnVtRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfU1RSSU5HX1BJRUNFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDI0OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLlN0cmluZz4gb3B0aW9uYWxTdHJpbmdQaWVjZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfQ09SRF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAyNTsKICAvKioKICAgKiA8cHJlPgogICAqIFRPRE86IGN0eXBlPUNPUkQgaXMgbm90IHN1cHBvcnRlZCBmb3IgZXh0ZW5zaW9uLiBBZGQKICAgKiBjdHlwZT1DT1JEIG9wdGlvbiBiYWNrIGFmdGVyIGl0IGlzIHN1cHBvcnRlZC4KICAgKiA8L3ByZT4KICAgKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLlN0cmluZz4gb3B0aW9uYWxDb3JkRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLlN0cmluZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9QVUJMSUNfSU1QT1JUX01FU1NBR0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjY7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZT4gb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0xBWllfTUVTU0FHRV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAyNzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gb3B0aW9uYWxMYXp5TWVzc2FnZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1VOVkVSSUZJRURfTEFaWV9NRVNTQUdFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDI4OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDMxOwogIC8qKgogICAqIDxwcmU+CiAgICogUmVwZWF0ZWQKICAgKiA8L3ByZT4KICAgKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+PiByZXBlYXRlZEludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfSU5UNjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMzI7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHJlcGVhdGVkSW50NjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9VSU5UMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMzM7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4+IHJlcGVhdGVkVWludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfVUlOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDM0OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+PiByZXBlYXRlZFVpbnQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1NJTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAzNTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPj4gcmVwZWF0ZWRTaW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TSU5UNjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMzY7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHJlcGVhdGVkU2ludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRklYRUQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAzNzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPj4gcmVwZWF0ZWRGaXhlZDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRklYRUQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAzODsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPj4gcmVwZWF0ZWRGaXhlZDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfU0ZJWEVEMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMzk7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4+IHJlcGVhdGVkU2ZpeGVkMzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TRklYRUQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA0MDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPj4gcmVwZWF0ZWRTZml4ZWQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0ZMT0FUX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDQxOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkZsb2F0Pj4gcmVwZWF0ZWRGbG9hdEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5GbG9hdC5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9ET1VCTEVfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDI7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRG91YmxlPj4gcmVwZWF0ZWREb3VibGVFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuRG91YmxlLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0JPT0xfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDM7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuQm9vbGVhbj4+IHJlcGVhdGVkQm9vbEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Cb29sZWFuLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1NUUklOR19FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA0NDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5TdHJpbmc+PiByZXBlYXRlZFN0cmluZ0V4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfQllURVNfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDU7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+PiByZXBlYXRlZEJ5dGVzRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVER1JPVVBfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDY7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlPj4gcmVwZWF0ZWRHcm91cEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfTkVTVEVEX01FU1NBR0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDg7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+PiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GT1JFSUdOX01FU1NBR0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDk7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+PiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmNsYXNzLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfSU1QT1JUX01FU1NBR0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNTA7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZT4+IHJlcGVhdGVkSW1wb3J0TWVzc2FnZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmNsYXNzLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9ORVNURURfRU5VTV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA1MTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bT4+IHJlcGVhdGVkTmVzdGVkRW51bUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GT1JFSUdOX0VOVU1fRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNTI7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+PiByZXBlYXRlZEZvcmVpZ25FbnVtRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lNUE9SVF9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDUzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGU+PiByZXBlYXRlZEltcG9ydEVudW1FeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TVFJJTkdfUElFQ0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNTQ7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuU3RyaW5nPj4gcmVwZWF0ZWRTdHJpbmdQaWVjZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfQ09SRF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA1NTsKICAvKioKICAgKiA8cHJlPgogICAqIFRPRE86IGN0eXBlPUNPUkQgaXMgbm90IHN1cHBvcnRlZCBmb3IgZXh0ZW5zaW9uLiBBZGQKICAgKiBjdHlwZT1DT1JEIG9wdGlvbiBiYWNrIGFmdGVyIGl0IGlzIHN1cHBvcnRlZC4KICAgKiA8L3ByZT4KICAgKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLlN0cmluZz4+IHJlcGVhdGVkQ29yZEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfTEFaWV9NRVNTQUdFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDU3OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPj4gcmVwZWF0ZWRMYXp5TWVzc2FnZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfSU5UMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNjE7CiAgLyoqCiAgICogPHByZT4KICAgKiBTaW5ndWxhciB3aXRoIGRlZmF1bHRzCiAgICogPC9wcmU+CiAgICoKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0SW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0lOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDYyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRJbnQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfVUlOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDYzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRVaW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1VJTlQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA2NDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0VWludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9TSU5UMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNjU7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdFNpbnQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU0lOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDY2OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRTaW50NjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0ZJWEVEMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNjc7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEZpeGVkMzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0ZJWEVENjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNjg7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdEZpeGVkNjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1NGSVhFRDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDY5OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRTZml4ZWQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU0ZJWEVENjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNzA7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9GTE9BVF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA3MTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5GbG9hdD4gZGVmYXVsdEZsb2F0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkZsb2F0LmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfRE9VQkxFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDcyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkRvdWJsZT4gZGVmYXVsdERvdWJsZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Eb3VibGUuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9CT09MX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDczOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkJvb2xlYW4+IGRlZmF1bHRCb29sRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkJvb2xlYW4uY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9TVFJJTkdfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNzQ7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuU3RyaW5nPiBkZWZhdWx0U3RyaW5nRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLlN0cmluZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0JZVEVTX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDc1OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBkZWZhdWx0Qnl0ZXNFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9ORVNURURfRU5VTV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA4MTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bT4gZGVmYXVsdE5lc3RlZEVudW1FeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9GT1JFSUdOX0VOVU1fRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gODI7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IGRlZmF1bHRGb3JlaWduRW51bUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0lNUE9SVF9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDgzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGU+IGRlZmF1bHRJbXBvcnRFbnVtRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9TVFJJTkdfUElFQ0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gODQ7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuU3RyaW5nPiBkZWZhdWx0U3RyaW5nUGllY2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfQ09SRF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA4NTsKICAvKioKICAgKiA8cHJlPgogICAqIFRPRE86IGN0eXBlPUNPUkQgaXMgbm90IHN1cHBvcnRlZCBmb3IgZXh0ZW5zaW9uLiBBZGQKICAgKiBjdHlwZT1DT1JEIG9wdGlvbiBiYWNrIGFmdGVyIGl0IGlzIHN1cHBvcnRlZC4KICAgKiA8L3ByZT4KICAgKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLlN0cmluZz4gZGVmYXVsdENvcmRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1VJTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMTE7CiAgLyoqCiAgICogPHByZT4KICAgKiBGb3Igb25lb2YgdGVzdAogICAqIDwvcHJlPgogICAqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gb25lb2ZVaW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9ORVNURURfTUVTU0FHRV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMTI7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IG9uZW9mTmVzdGVkTWVzc2FnZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1NUUklOR19FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMTM7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuU3RyaW5nPiBvbmVvZlN0cmluZ0V4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfQllURVNfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTE0OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBvbmVvZkJ5dGVzRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9JTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5MDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPj4gcGFja2VkSW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfSU5UNjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gOTE7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHBhY2tlZEludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1VJTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5MjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPj4gcGFja2VkVWludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1VJTlQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5MzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPj4gcGFja2VkVWludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1NJTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5NDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPj4gcGFja2VkU2ludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1NJTlQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5NTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPj4gcGFja2VkU2ludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0ZJWEVEMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gOTY7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4+IHBhY2tlZEZpeGVkMzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfRklYRUQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5NzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPj4gcGFja2VkRml4ZWQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9TRklYRUQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5ODsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPj4gcGFja2VkU2ZpeGVkMzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfU0ZJWEVENjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gOTk7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90bzJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHBhY2tlZFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0ZMT0FUX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDEwMDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5GbG9hdD4+IHBhY2tlZEZsb2F0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkZsb2F0LmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9ET1VCTEVfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTAxOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkRvdWJsZT4+IHBhY2tlZERvdWJsZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Eb3VibGUuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0JPT0xfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTAyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkJvb2xlYW4+PiBwYWNrZWRCb29sRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkJvb2xlYW4uY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0VOVU1fRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTAzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPj4gcGFja2VkRW51bUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBURVNUX0FMTF9UWVBFU19MSVRFX0ZJRUxEX05VTUJFUiA9IDUzNjg2MDAwMDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IHRlc3RBbGxUeXBlc0xpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2VfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZTJfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZTJfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfUmVwZWF0ZWRHcm91cF9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9SZXBlYXRlZEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3ROZXN0ZWRFeHRlbnNpb25MaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdERlcHJlY2F0ZWRMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDFfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMl9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAyX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkR3JvdXBfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVyZ2VFeGNlcHRpb25MaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVyZ2VFeGNlcHRpb25MaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YxTWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YxTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9WMk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9WMk1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX09wdGlvbmFsR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfU3RyaW5nU3RyaW5nTWFwRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9TdHJpbmdTdHJpbmdNYXBFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RPbmVvZlBhcnNpbmdMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlU2V0TGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VTZXRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkSW50MzJfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1BhY2tlZEludDMyX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkSW50MzJfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X05vblBhY2tlZEZpeGVkMzJfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X05vblBhY2tlZEZpeGVkMzJfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9EdXBFbnVtX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9EdXBFbnVtX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVjdXJzaXZlTWVzc2FnZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVjdXJzaXZlTWVzc2FnZV9maWVsZEFjY2Vzc29yVGFibGU7CgogIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgcmV0dXJuIGRlc2NyaXB0b3I7CiAgfQogIHByaXZhdGUgc3RhdGljICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIGRlc2NyaXB0b3I7CiAgc3RhdGljIHsKICAgIGphdmEubGFuZy5TdHJpbmdbXSBkZXNjcmlwdG9yRGF0YSA9IHsKICAgICAgIlxuI2dvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvXDAyMlwwMTdwIiArCiAgICAgICJyb3RvMl91bml0dGVzdFwwMzIqZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0IiArCiAgICAgICJfaW1wb3J0X2xpdGUucHJvdG9cIlwyMDVcMDM0XG5cMDIwVGVzdEFsbFR5cGVzTGl0ZVwwMjIiICsKICAgICAgIlwwMjZcblwwMTZvcHRpb25hbF9pbnQzMlwwMzBcMDAxIFwwMDEoXDAwNVwwMjJcMDI2XG5cMDE2b3B0aW9uYWxfaW50NiIgKwogICAgICAiNFwwMzBcMDAyIFwwMDEoXDAwM1wwMjJcMDI3XG5cMDE3b3B0aW9uYWxfdWludDMyXDAzMFwwMDMgXDAwMShcclwwMjJcMDI3XG5cMDE3b3B0aSIgKwogICAgICAib25hbF91aW50NjRcMDMwXDAwNCBcMDAxKFwwMDRcMDIyXDAyN1xuXDAxN29wdGlvbmFsX3NpbnQzMlwwMzBcMDA1IFwwMDEiICsKICAgICAgIihcMDIxXDAyMlwwMjdcblwwMTdvcHRpb25hbF9zaW50NjRcMDMwXDAwNiBcMDAxKFwwMjJcMDIyXDAzMFxuXDAyMG9wdGlvbmFsXyIgKwogICAgICAiZml4ZWQzMlwwMzBcMDA3IFwwMDEoXDAwN1wwMjJcMDMwXG5cMDIwb3B0aW9uYWxfZml4ZWQ2NFwwMzBcMDEwIFwwMDEoXDAwNlwwMjIiICsKICAgICAgIlwwMzFcblwwMjFvcHRpb25hbF9zZml4ZWQzMlwwMzBcdCBcMDAxKFwwMTdcMDIyXDAzMVxuXDAyMW9wdGlvbmFsX3MiICsKICAgICAgImZpeGVkNjRcMDMwXG4gXDAwMShcMDIwXDAyMlwwMjZcblwwMTZvcHRpb25hbF9mbG9hdFwwMzBcMDEzIFwwMDEoXDAwMlwwMjJcMDI3XG4iICsKICAgICAgIlwwMTdvcHRpb25hbF9kb3VibGVcMDMwXDAxNCBcMDAxKFwwMDFcMDIyXDAyNVxuXHJvcHRpb25hbF9ib29sXDAzMCIgKwogICAgICAiXHIgXDAwMShcMDEwXDAyMlwwMjdcblwwMTdvcHRpb25hbF9zdHJpbmdcMDMwXDAxNiBcMDAxKFx0XDAyMlwwMjZcblwwMTZvcHRpb24iICsKICAgICAgImFsX2J5dGVzXDAzMFwwMTcgXDAwMShcMDE0XDAyMkZcblxyb3B0aW9uYWxncm91cFwwMzBcMDIwIFwwMDEoXG4yLy4iICsKICAgICAgInByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmEiICsKICAgICAgImxHcm91cFwwMjJQXG5cMDI3b3B0aW9uYWxfbmVzdGVkX21lc3NhZ2VcMDMwXDAyMiBcMDAxKFwwMTMyIiArCiAgICAgICIvLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlIiArCiAgICAgICJkTWVzc2FnZVwwMjJFXG5cMDMwb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlXDAzMFwwMjMgXDAwMSIgKwogICAgICAiKFwwMTMyIy5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlXDAyMiIgKwogICAgICAiTFxuXDAyN29wdGlvbmFsX2ltcG9ydF9tZXNzYWdlXDAzMFwwMjQgXDAwMShcMDEzMisucHJvdG8iICsKICAgICAgImJ1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGVcMDIySlxuIiArCiAgICAgICJcMDI0b3B0aW9uYWxfbmVzdGVkX2VudW1cMDMwXDAyNSBcMDAxKFwwMTYyLC5wcm90bzJfdW5pIiArCiAgICAgICJ0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW1cMDIyP1xuXDAyNW9wdCIgKwogICAgICAiaW9uYWxfZm9yZWlnbl9lbnVtXDAzMFwwMjYgXDAwMShcMDE2MiAucHJvdG8yX3VuaXR0ZSIgKwogICAgICAic3QuRm9yZWlnbkVudW1MaXRlXDAyMkZcblwwMjRvcHRpb25hbF9pbXBvcnRfZW4iICsKICAgICAgInVtXDAzMFwwMjcgXDAwMShcMDE2MigucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG8iICsKICAgICAgInJ0RW51bUxpdGVcMDIyIVxuXDAyNW9wdGlvbmFsX3N0cmluZ19waWVjZVwwMzBcMDMwIFwwMDEoIiArCiAgICAgICJcdEJcMDAyXDAxMFwwMDJcMDIyXDAzMVxuXHJvcHRpb25hbF9jb3JkXDAzMFwwMzEgXDAwMShcdEJcMDAyXDAxMFwwMDFcMDIyWVxuXDAzNm9wdGkiICsKICAgICAgIm9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlXDAzMFwwMzIgXDAwMShcMDEzMjEucHJvdG8iICsKICAgICAgImJ1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUwiICsKICAgICAgIml0ZVwwMjJSXG5cMDI1b3B0aW9uYWxfbGF6eV9tZXNzYWdlXDAzMFwwMzMgXDAwMShcMDEzMi8ucHJvIiArCiAgICAgICJ0bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzIiArCiAgICAgICJhZ2VCXDAwMihcMDAxXDAyMl1cbiBvcHRpb25hbF91bnZlcmlmaWVkX2xhenlfbWVzcyIgKwogICAgICAiYWdlXDAzMFwwMzQgXDAwMShcMDEzMi8ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcyIgKwogICAgICAiTGl0ZS5OZXN0ZWRNZXNzYWdlQlwwMDJ4XDAwMVwwMjJcMDI2XG5cMDE2cmVwZWF0ZWRfaW50MzIiICsKICAgICAgIlwwMzBcMDM3IFwwMDMoXDAwNVwwMjJcMDI2XG5cMDE2cmVwZWF0ZWRfaW50NjRcMDMwICBcMDAzKFwwMDNcMDIyXDAyN1xuXDAxN3JlcGVhdCIgKwogICAgICAiZWRfdWludDMyXDAzMCEgXDAwMyhcclwwMjJcMDI3XG5cMDE3cmVwZWF0ZWRfdWludDY0XDAzMFwiIFwwMDMoXDAwNCIgKwogICAgICAiXDAyMlwwMjdcblwwMTdyZXBlYXRlZF9zaW50MzJcMDMwIyBcMDAzKFwwMjFcMDIyXDAyN1xuXDAxN3JlcGVhdGVkX3NpIiArCiAgICAgICJudDY0XDAzMCQgXDAwMyhcMDIyXDAyMlwwMzBcblwwMjByZXBlYXRlZF9maXhlZDMyXDAzMCUgXDAwMyhcMDA3XDAyMlwwMzBcblwwMjAiICsKICAgICAgInJlcGVhdGVkX2ZpeGVkNjRcMDMwJiBcMDAzKFwwMDZcMDIyXDAzMVxuXDAyMXJlcGVhdGVkX3NmaXhlIiArCiAgICAgICJkMzJcMDMwXCcgXDAwMyhcMDE3XDAyMlwwMzFcblwwMjFyZXBlYXRlZF9zZml4ZWQ2NFwwMzAoIFwwMDMoXDAyMFwwMjJcMDI2XG5cMDE2IiArCiAgICAgICJyZXBlYXRlZF9mbG9hdFwwMzApIFwwMDMoXDAwMlwwMjJcMDI3XG5cMDE3cmVwZWF0ZWRfZG91YmxlXDAzMCIgKwogICAgICAiKiBcMDAzKFwwMDFcMDIyXDAyNVxuXHJyZXBlYXRlZF9ib29sXDAzMCsgXDAwMyhcMDEwXDAyMlwwMjdcblwwMTdyZXBlYXRlZCIgKwogICAgICAiX3N0cmluZ1wwMzAsIFwwMDMoXHRcMDIyXDAyNlxuXDAxNnJlcGVhdGVkX2J5dGVzXDAzMC0gXDAwMyhcMDE0XDAyMkZcbiIgKwogICAgICAiXHJyZXBlYXRlZGdyb3VwXDAzMC4gXDAwMyhcbjIvLnByb3RvMl91bml0dGVzdC5UIiArCiAgICAgICJlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cFwwMjJQXG5cMDI3cmVwZWF0ZSIgKwogICAgICAiZF9uZXN0ZWRfbWVzc2FnZVwwMzAwIFwwMDMoXDAxMzIvLnByb3RvMl91bml0dGVzdCIgKwogICAgICAiLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZVwwMjJFXG5cMDMwcmVwZWEiICsKICAgICAgInRlZF9mb3JlaWduX21lc3NhZ2VcMDMwMSBcMDAzKFwwMTMyIy5wcm90bzJfdW5pdHQiICsKICAgICAgImVzdC5Gb3JlaWduTWVzc2FnZUxpdGVcMDIyTFxuXDAyN3JlcGVhdGVkX2ltcG9yIiArCiAgICAgICJ0X21lc3NhZ2VcMDMwMiBcMDAzKFwwMTMyKy5wcm90b2J1Zl91bml0dGVzdF9pbXBvIiArCiAgICAgICJydC5JbXBvcnRNZXNzYWdlTGl0ZVwwMjJKXG5cMDI0cmVwZWF0ZWRfbmVzdGVkXyIgKwogICAgICAiZW51bVwwMzAzIFwwMDMoXDAxNjIsLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZSIgKwogICAgICAic0xpdGUuTmVzdGVkRW51bVwwMjI/XG5cMDI1cmVwZWF0ZWRfZm9yZWlnbl9lbnUiICsKICAgICAgIm1cMDMwNCBcMDAzKFwwMTYyIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXQiICsKICAgICAgImVcMDIyRlxuXDAyNHJlcGVhdGVkX2ltcG9ydF9lbnVtXDAzMDUgXDAwMyhcMDE2MigucHJvdG9iIiArCiAgICAgICJ1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGVcMDIyIVxuXDAyNXJlcCIgKwogICAgICAiZWF0ZWRfc3RyaW5nX3BpZWNlXDAzMDYgXDAwMyhcdEJcMDAyXDAxMFwwMDJcMDIyXDAzMVxuXHJyZXBlYXRlZCIgKwogICAgICAiX2NvcmRcMDMwNyBcMDAzKFx0QlwwMDJcMDEwXDAwMVwwMjJSXG5cMDI1cmVwZWF0ZWRfbGF6eV9tZXNzYWdlIiArCiAgICAgICJcMDMwOSBcMDAzKFwwMTMyLy5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0IiArCiAgICAgICJlLk5lc3RlZE1lc3NhZ2VCXDAwMihcMDAxXDAyMlwwMzFcblxyZGVmYXVsdF9pbnQzMlwwMzA9IFwwMDEiICsKICAgICAgIihcMDA1OlwwMDI0MVwwMjJcMDMxXG5ccmRlZmF1bHRfaW50NjRcMDMwPiBcMDAxKFwwMDM6XDAwMjQyXDAyMlwwMzJcblwwMTZkZWYiICsKICAgICAgImF1bHRfdWludDMyXDAzMD8gXDAwMShccjpcMDAyNDNcMDIyXDAzMlxuXDAxNmRlZmF1bHRfdWludDY0XDAzMCIgKwogICAgICAiQCBcMDAxKFwwMDQ6XDAwMjQ0XDAyMlwwMzNcblwwMTZkZWZhdWx0X3NpbnQzMlwwMzBBIFwwMDEoXDAyMTpcMDAzLTQ1XDAyMlwwMzIiICsKICAgICAgIlxuXDAxNmRlZmF1bHRfc2ludDY0XDAzMEIgXDAwMShcMDIyOlwwMDI0NlwwMjJcMDMzXG5cMDE3ZGVmYXVsdF9maSIgKwogICAgICAieGVkMzJcMDMwQyBcMDAxKFwwMDc6XDAwMjQ3XDAyMlwwMzNcblwwMTdkZWZhdWx0X2ZpeGVkNjRcMDMwRCBcMDAxKFwwMDYiICsKICAgICAgIjpcMDAyNDhcMDIyXDAzNFxuXDAyMGRlZmF1bHRfc2ZpeGVkMzJcMDMwRSBcMDAxKFwwMTc6XDAwMjQ5XDAyMlwwMzVcblwwMjBkZSIgKwogICAgICAiZmF1bHRfc2ZpeGVkNjRcMDMwRiBcMDAxKFwwMjA6XDAwMy01MFwwMjJcMDMzXG5ccmRlZmF1bHRfZmxvIiArCiAgICAgICJhdFwwMzBHIFwwMDEoXDAwMjpcMDA0NTEuNVwwMjJcMDM1XG5cMDE2ZGVmYXVsdF9kb3VibGVcMDMwSCBcMDAxKFwwMDE6XDAwNSIgKwogICAgICAiNTIwMDBcMDIyXDAzMlxuXDAxNGRlZmF1bHRfYm9vbFwwMzBJIFwwMDEoXDAxMDpcMDA0dHJ1ZVwwMjJcMDM1XG5cMDE2ZGVmIiArCiAgICAgICJhdWx0X3N0cmluZ1wwMzBKIFwwMDEoXHQ6XDAwNWhlbGxvXDAyMlwwMzRcblxyZGVmYXVsdF9ieXRlIiArCiAgICAgICJzXDAzMEsgXDAwMShcMDE0OlwwMDV3b3JsZFwwMjJOXG5cMDIzZGVmYXVsdF9uZXN0ZWRfZW51bVwwMzBRICIgKwogICAgICAiXDAwMShcMDE2MiwucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTiIgKwogICAgICAiZXN0ZWRFbnVtOlwwMDNCQVJcMDIyUFxuXDAyNGRlZmF1bHRfZm9yZWlnbl9lbnVtXDAzMFIiICsKICAgICAgIiBcMDAxKFwwMTYyIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlOlwwMjAiICsKICAgICAgIkZPUkVJR05fTElURV9CQVJcMDIyVlxuXDAyM2RlZmF1bHRfaW1wb3J0X2VudW1cMDMwIiArCiAgICAgICJTIFwwMDEoXDAxNjIoLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFIiArCiAgICAgICJudW1MaXRlOlwwMTdJTVBPUlRfTElURV9CQVJcMDIyJVxuXDAyNGRlZmF1bHRfc3RyaSIgKwogICAgICAibmdfcGllY2VcMDMwVCBcMDAxKFx0OlwwMDNhYmNCXDAwMlwwMTBcMDAyXDAyMlwwMzVcblwwMTRkZWZhdWx0X2NvcmRcMDMwIiArCiAgICAgICJVIFwwMDEoXHQ6XDAwMzEyM0JcMDAyXDAxMFwwMDFcMDIyXDAyNlxuXDAxNG9uZW9mX3VpbnQzMlwwMzBvIFwwMDEoXHJIXDAwMFwwMjJPIiArCiAgICAgICJcblwwMjRvbmVvZl9uZXN0ZWRfbWVzc2FnZVwwMzBwIFwwMDEoXDAxMzIvLnByb3RvMl91biIgKwogICAgICAiaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZUhcMDAwXDAyMiIgKwogICAgICAiXDAyNlxuXDAxNG9uZW9mX3N0cmluZ1wwMzBxIFwwMDEoXHRIXDAwMFwwMjJcMDI1XG5cMDEzb25lb2ZfYnl0ZXNcMDMwciIgKwogICAgICAiIFwwMDEoXDAxNEhcMDAwXDAyMlhcblwwMzFvbmVvZl9sYXp5X25lc3RlZF9tZXNzYWdlXDAzMHMgXDAwMSgiICsKICAgICAgIlwwMTMyLy5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXMiICsKICAgICAgInRlZE1lc3NhZ2VCXDAwMihcMDAxSFwwMDBcMDIyUVxuXDAyNW9uZW9mX25lc3RlZF9tZXNzYWdlIiArCiAgICAgICIyXDAzMHUgXDAwMShcMDEzMjAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpIiArCiAgICAgICJ0ZS5OZXN0ZWRNZXNzYWdlMkhcMDAwXDAyMlwwMzZcblwwMjZkZWNlcHRpdmVseV9uYW1lZCIgKwogICAgICAiX2xpc3RcMDMwdCBcMDAxKFwwMDVcMDMyN1xuXHJOZXN0ZWRNZXNzYWdlXDAyMlxuXG5cMDAyYmJcMDMwXDAwMSBcMDAxKFwwMDUiICsKICAgICAgIlwwMjJcblxuXDAwMmNjXDAzMFwwMDIgXDAwMShcMDAzXDAyMlwwMTZcblwwMDJkZFwwMzBcMDAzIFwwMDMoXDAwNUJcMDAyXDAyMFwwMDFcMDMyXDAzNFxuXDAxNk5lc3RlZE1lIiArCiAgICAgICJzc2FnZTJcMDIyXG5cblwwMDJkZFwwMzBcMDAxIFwwMDEoXDAwNVwwMzJcMDMyXG5cck9wdGlvbmFsR3JvdXBcMDIyXHRcblwwMDFhIiArCiAgICAgICJcMDMwXDAyMSBcMDAxKFwwMDVcMDMyXDAzMlxuXHJSZXBlYXRlZEdyb3VwXDAyMlx0XG5cMDAxYVwwMzAvIFwwMDEoXDAwNVwiXCdcblxuTmUiICsKICAgICAgInN0ZWRFbnVtXDAyMlwwMDdcblwwMDNGT09cMDIwXDAwMVwwMjJcMDA3XG5cMDAzQkFSXDAyMFwwMDJcMDIyXDAwN1xuXDAwM0JBWlwwMjBcMDAzQlxyXG5cMDEzbyIgKwogICAgICAibmVvZl9maWVsZFwiXDAzN1xuXDAyMkZvcmVpZ25NZXNzYWdlTGl0ZVwwMjJcdFxuXDAwMWNcMDMwXDAwMSAiICsKICAgICAgIlwwMDEoXDAwNVwiXDI2MFwwMDNcblwwMjNUZXN0UGFja2VkVHlwZXNMaXRlXDAyMlwwMzBcblwwMTRwYWNrZWRfaW4iICsKICAgICAgInQzMlwwMzBaIFwwMDMoXDAwNUJcMDAyXDAyMFwwMDFcMDIyXDAzMFxuXDAxNHBhY2tlZF9pbnQ2NFwwMzBbIFwwMDMoXDAwM0JcMDAyXDAyMFwwMDFcMDIyIiArCiAgICAgICJcMDMxXG5ccnBhY2tlZF91aW50MzJcMDMwXFwgXDAwMyhcckJcMDAyXDAyMFwwMDFcMDIyXDAzMVxuXHJwYWNrZWRfdWluIiArCiAgICAgICJ0NjRcMDMwXSBcMDAzKFwwMDRCXDAwMlwwMjBcMDAxXDAyMlwwMzFcblxycGFja2VkX3NpbnQzMlwwMzBeIFwwMDMoXDAyMUJcMDAyXDAyMFwwMDEiICsKICAgICAgIlwwMjJcMDMxXG5ccnBhY2tlZF9zaW50NjRcMDMwXyBcMDAzKFwwMjJCXDAwMlwwMjBcMDAxXDAyMlwwMzJcblwwMTZwYWNrZWRfZmkiICsKICAgICAgInhlZDMyXDAzMGAgXDAwMyhcMDA3QlwwMDJcMDIwXDAwMVwwMjJcMDMyXG5cMDE2cGFja2VkX2ZpeGVkNjRcMDMwYSBcMDAzKFwwMDZCIiArCiAgICAgICJcMDAyXDAyMFwwMDFcMDIyXDAzM1xuXDAxN3BhY2tlZF9zZml4ZWQzMlwwMzBiIFwwMDMoXDAxN0JcMDAyXDAyMFwwMDFcMDIyXDAzM1xuXDAxN3BhY2siICsKICAgICAgImVkX3NmaXhlZDY0XDAzMGMgXDAwMyhcMDIwQlwwMDJcMDIwXDAwMVwwMjJcMDMwXG5cMDE0cGFja2VkX2Zsb2F0XDAzMGQgIiArCiAgICAgICJcMDAzKFwwMDJCXDAwMlwwMjBcMDAxXDAyMlwwMzFcblxycGFja2VkX2RvdWJsZVwwMzBlIFwwMDMoXDAwMUJcMDAyXDAyMFwwMDFcMDIyXDAyN1xuXDAxM3BhIiArCiAgICAgICJja2VkX2Jvb2xcMDMwZiBcMDAzKFwwMTBCXDAwMlwwMjBcMDAxXDAyMjlcblwwMTNwYWNrZWRfZW51bVwwMzBnIFwwMDMoXDAxNiIgKwogICAgICAiMiAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZUJcMDAyXDAyMFwwMDFcIiEiICsKICAgICAgIlxuXDAyNVRlc3RBbGxFeHRlbnNpb25zTGl0ZSpcMDEwXDAxMFwwMDFcMDIwXDIwMFwyMDBcMjAwXDIwMFwwMDJcIilcblwwMzRPcHQiICsKICAgICAgImlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVcMDIyXHRcblwwMDFhXDAzMFwwMjEgXDAwMShcMDA1XCIpXG5cMDM0IiArCiAgICAgICJSZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlXDAyMlx0XG5cMDAxYVwwMzAvIFwwMDEoXDAwNVwiIiArCiAgICAgICIkXG5cMDMwVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKlwwMTBcMDEwXDAwMVwwMjBcMjAwXDIwMFwyMDBcMjAwXDAwMlwiXFxcbiIgKwogICAgICAiXDAyN1Rlc3ROZXN0ZWRFeHRlbnNpb25MaXRlMkFcblwwMjBuZXN0ZWRfZXh0ZW4iICsKICAgICAgInNpb25cMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMiICsKICAgICAgIkxpdGVcMDMwXDI3MWAgXDAwMShcMDA1XCJcMjY0XDAwMVxuXDAyMlRlc3REZXByZWNhdGVkTGl0ZVwwMjJcMDM0XG5cMDIwZGUiICsKICAgICAgInByZWNhdGVkX2ZpZWxkXDAzMFwwMDEgXDAwMShcMDA1QlwwMDJcMDMwXDAwMVwwMjJcMDM1XG5cMDIxZGVwcmVjYXRlZF9mIiArCiAgICAgICJpZWxkMlwwMzBcMDAyIFwwMDIoXDAwNUJcMDAyXDAzMFwwMDFcMDIyXDAzNVxuXDAyMWRlcHJlY2F0ZWRfZmllbGQzXDAzMFwwMDMgXDAwMSIgKwogICAgICAiKFx0QlwwMDJcMDMwXDAwMVwwMjJCXG5cMDIxZGVwcmVjYXRlZF9maWVsZDRcMDMwXDAwNCBcMDAxKFwwMTMyIy5wcm90IiArCiAgICAgICJvMl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGVCXDAwMlwwMzBcMDAxXCJcMjQzXG5cblwwMjRUIiArCiAgICAgICJlc3RQYXJzaW5nTWVyZ2VMaXRlXDAyMj1cblwwMjJyZXF1aXJlZF9hbGxfdHlwZSIgKwogICAgICAic1wwMzBcMDAxIFwwMDIoXDAxMzIhLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaSIgKwogICAgICAidGVcMDIyPVxuXDAyMm9wdGlvbmFsX2FsbF90eXBlc1wwMzBcMDAyIFwwMDEoXDAxMzIhLnByb3RvMl8iICsKICAgICAgInVuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGVcMDIyPVxuXDAyMnJlcGVhdGVkX2FsIiArCiAgICAgICJsX3R5cGVzXDAzMFwwMDMgXDAwMyhcMDEzMiEucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUIiArCiAgICAgICJ5cGVzTGl0ZVwwMjJKXG5ccm9wdGlvbmFsZ3JvdXBcMDMwXG4gXDAwMShcbjIzLnByb3RvMiIgKwogICAgICAiX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsRyIgKwogICAgICAicm91cFwwMjJKXG5ccnJlcGVhdGVkZ3JvdXBcMDMwXDAyNCBcMDAzKFxuMjMucHJvdG8yX3VuaSIgKwogICAgICAidHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCIgKwogICAgICAiXDAzMlwyNzRcMDA0XG5cMDI3UmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JcMDIyMVxuXDAwNmZpZWxkMVwwMzBcMDAxIiArCiAgICAgICIgXDAwMyhcMDEzMiEucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGVcMDIyIiArCiAgICAgICIxXG5cMDA2ZmllbGQyXDAzMFwwMDIgXDAwMyhcMDEzMiEucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbCIgKwogICAgICAibFR5cGVzTGl0ZVwwMjIxXG5cMDA2ZmllbGQzXDAzMFwwMDMgXDAwMyhcMDEzMiEucHJvdG8yX3VuaXQiICsKICAgICAgInRlc3QuVGVzdEFsbFR5cGVzTGl0ZVwwMjJUXG5cMDA2Z3JvdXAxXDAzMFxuIFwwMDMoXG4yRC4iICsKICAgICAgInByb3RvMl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXAiICsKICAgICAgImVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMVwwMjJUXG5cMDA2Z3JvdXAyXDAzMFwwMjQgIiArCiAgICAgICJcMDAzKFxuMkQucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaSIgKwogICAgICAidGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyXDAyMjBcblwwMDRleHQiICsKICAgICAgIjFcMDMwXDM1MFwwMDcgXDAwMyhcMDEzMiEucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0wiICsKICAgICAgIml0ZVwwMjIwXG5cMDA0ZXh0MlwwMzBcMzUxXDAwNyBcMDAzKFwwMTMyIS5wcm90bzJfdW5pdHRlc3QuVGVzIiArCiAgICAgICJ0QWxsVHlwZXNMaXRlXDAzMjtcblwwMDZHcm91cDFcMDIyMVxuXDAwNmZpZWxkMVwwMzBcMDEzIFwwMDEoXDAxMzIiICsKICAgICAgIiEucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGVcMDMyO1xuXDAwNkdyIiArCiAgICAgICJvdXAyXDAyMjFcblwwMDZmaWVsZDFcMDMwXDAyNSBcMDAxKFwwMTMyIS5wcm90bzJfdW5pdHRlc3QuVCIgKwogICAgICAiZXN0QWxsVHlwZXNMaXRlXDAzMlRcblxyT3B0aW9uYWxHcm91cFwwMjJDXG5cMDMwb3B0aSIgKwogICAgICAib25hbF9ncm91cF9hbGxfdHlwZXNcMDMwXDAxMyBcMDAxKFwwMTMyIS5wcm90bzJfdW5pdCIgKwogICAgICAidGVzdC5UZXN0QWxsVHlwZXNMaXRlXDAzMlRcblxyUmVwZWF0ZWRHcm91cFwwMjJDIiArCiAgICAgICJcblwwMzByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXNcMDMwXDAyNSBcMDAxKFwwMTMyIS5wcm90byIgKwogICAgICAiMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlKlx0XDAxMFwzNTBcMDA3XDAyMFwyMDBcMjAwXDIwMFwyMDBcMDAyMl8iICsKICAgICAgIlxuXDAxNG9wdGlvbmFsX2V4dFwwMjIlLnByb3RvMl91bml0dGVzdC5UZXN0UGFyIiArCiAgICAgICJzaW5nTWVyZ2VMaXRlXDAzMFwzNTBcMDA3IFwwMDEoXDAxMzIhLnByb3RvMl91bml0dGVzdC5UIiArCiAgICAgICJlc3RBbGxUeXBlc0xpdGUyX1xuXDAxNHJlcGVhdGVkX2V4dFwwMjIlLnByb3RvMiIgKwogICAgICAiX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlXDAzMFwzNTFcMDA3IFwwMDMoXDAxMzIhLiIgKwogICAgICAicHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGVcIlhcblwwMjZUZXN0IiArCiAgICAgICJNZXJnZUV4Y2VwdGlvbkxpdGVcMDIyPlxuXDAxNmFsbF9leHRlbnNpb25zXDAzMFwwMDEgXDAwMSIgKwogICAgICAiKFwwMTMyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaSIgKwogICAgICAidGVcIlwwMjZcblwwMjRUZXN0RW1wdHlNZXNzYWdlTGl0ZVwiLlxuXCJUZXN0RW1wdHlNIiArCiAgICAgICJlc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUqXDAxMFwwMTBcMDAxXDAyMFwyMDBcMjAwXDIwMFwyMDBcMDAyXCJdXG5cclYxIiArCiAgICAgICJNZXNzYWdlTGl0ZVwwMjJcMDIxXG5cdGludF9maWVsZFwwMzBcMDAxIFwwMDIoXDAwNVwwMjI5XG5cbmVudW1fZiIgKwogICAgICAiaWVsZFwwMzBcMDAyIFwwMDEoXDAxNjJcMDMzLnByb3RvMl91bml0dGVzdC5WMUVudW1MaXRlOiIgKwogICAgICAiXDAxMFYxX0ZJUlNUXCJdXG5cclYyTWVzc2FnZUxpdGVcMDIyXDAyMVxuXHRpbnRfZmllbGRcMDMwIiArCiAgICAgICJcMDAxIFwwMDIoXDAwNVwwMjI5XG5cbmVudW1fZmllbGRcMDMwXDAwMiBcMDAxKFwwMTYyXDAzMy5wcm90bzJfdW5pdHQiICsKICAgICAgImVzdC5WMkVudW1MaXRlOlwwMTBWMl9GSVJTVFwiXDIxM1wwMDZcblwwMzBUZXN0SHVnZUZpZSIgKwogICAgICAibGROdW1iZXJzTGl0ZVwwMjJcMDMyXG5cMDE2b3B0aW9uYWxfaW50MzJcMDMwXDM2MFwzNzBcMzc3XDM3N1wwMDEgXDAwMSgiICsKICAgICAgIlwwMDVcMDIyXDAyNFxuXDAxMGZpeGVkXzMyXDAzMFwzNjFcMzcwXDM3N1wzNzdcMDAxIFwwMDEoXDAwNVwwMjJcMDM2XG5cMDE2cmVwZWF0ZWRfaW50MyIgKwogICAgICAiMlwwMzBcMzYyXDM3MFwzNzdcMzc3XDAwMSBcMDAzKFwwMDVCXDAwMlwwMjBcMDAwXDAyMlwwMzRcblwwMTRwYWNrZWRfaW50MzJcMDMwXDM2M1wzNzBcMzc3XDM3N1wwMDEgXDAwMygiICsKICAgICAgIlwwMDVCXDAwMlwwMjBcMDAxXDAyMjtcblxyb3B0aW9uYWxfZW51bVwwMzBcMzY0XDM3MFwzNzdcMzc3XDAwMSBcMDAxKFwwMTYyIC5wcm90byIgKwogICAgICAiMl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGVcMDIyXDAzM1xuXDAxN29wdGlvbmFsX3MiICsKICAgICAgInRyaW5nXDAzMFwzNjVcMzcwXDM3N1wzNzdcMDAxIFwwMDEoXHRcMDIyXDAzMlxuXDAxNm9wdGlvbmFsX2J5dGVzXDAzMFwzNjZcMzcwXDM3N1wzNzdcMDAxICIgKwogICAgICAiXDAwMShcMDE0XDAyMkFcblwwMjBvcHRpb25hbF9tZXNzYWdlXDAzMFwzNjdcMzcwXDM3N1wzNzdcMDAxIFwwMDEoXDAxMzIjLnByb3QiICsKICAgICAgIm8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZVwwMjJSXG5ccm9wdGlvbiIgKwogICAgICAiYWxncm91cFwwMzBcMzcwXDM3MFwzNzdcMzc3XDAwMSBcMDAxKFxuMjcucHJvdG8yX3VuaXR0ZXN0LlRlc3QiICsKICAgICAgIkh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXBcMDIyXVxuXDAyMXN0IiArCiAgICAgICJyaW5nX3N0cmluZ19tYXBcMDMwXDM3MlwzNzBcMzc3XDM3N1wwMDEgXDAwMyhcMDEzMj4ucHJvdG8yX3VuaXR0IiArCiAgICAgICJlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLlN0cmluZ1N0cmluIiArCiAgICAgICJnTWFwRW50cnlcMDIyXDAzMlxuXDAxNG9uZW9mX3VpbnQzMlwwMzBcMzczXDM3MFwzNzdcMzc3XDAwMSBcMDAxKFxySFwwMDBcMDIyRVxuIiArCiAgICAgICJcMDI0b25lb2ZfdGVzdF9hbGxfdHlwZXNcMDMwXDM3NFwzNzBcMzc3XDM3N1wwMDEgXDAwMShcMDEzMiEucHJvdG8yIiArCiAgICAgICJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZUhcMDAwXDAyMlwwMzJcblwwMTRvbmVvZl9zdCIgKwogICAgICAicmluZ1wwMzBcMzc1XDM3MFwzNzdcMzc3XDAwMSBcMDAxKFx0SFwwMDBcMDIyXDAzMVxuXDAxM29uZW9mX2J5dGVzXDAzMFwzNzZcMzcwXDM3N1wzNzdcMDAxIFwwMDEoIiArCiAgICAgICJcMDE0SFwwMDBcMDMyJFxuXHJPcHRpb25hbEdyb3VwXDAyMlwwMjNcblwwMDdncm91cF9hXDAzMFwzNzFcMzcwXDM3N1wzNzdcMDAxIFwwMDEoIiArCiAgICAgICJcMDA1XDAzMjZcblwwMjRTdHJpbmdTdHJpbmdNYXBFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcdFwwMjJcciIgKwogICAgICAiXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFx0OlwwMDI4XDAwMSpcMDE0XDAxMFwzNDBcMjUyXDM3N1wzNzdcMDAxXDAyMFwzNjBcMzcwXDM3N1wzNzdcMDAxQlxyXG5cMDEzb25lb2YiICsKICAgICAgIl9maWVsZFwiXDI0MVwwMDNcblwwMjRUZXN0T25lb2ZQYXJzaW5nTGl0ZVwwMjJcMDI1XG5cMDEzb25lb2YiICsKICAgICAgIl9pbnQzMlwwMzBcMDAxIFwwMDEoXDAwNUhcMDAwXDAyMj1cblwwMjBvbmVvZl9zdWJtZXNzYWdlXDAzMFwwMDIgXDAwMShcMDEzIiArCiAgICAgICIyIS5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZUhcMDAwXDAyMlwwMjZcbiIgKwogICAgICAiXDAxNG9uZW9mX3N0cmluZ1wwMzBcMDAzIFwwMDEoXHRIXDAwMFwwMjIkXG5cMDEzb25lb2ZfYnl0ZXNcMDMwXDAwNCBcMDAxIiArCiAgICAgICIoXDAxNDpccmRlZmF1bHQgYnl0ZXNIXDAwMFwwMjItXG5cMDIxb25lb2Zfc3RyaW5nX2NvcmQiICsKICAgICAgIlwwMzBcMDA1IFwwMDEoXHQ6XDAxNGRlZmF1bHQgQ29yZEJcMDAyXDAxMFwwMDFIXDAwMFwwMjJcMDM2XG5cMDIwb25lb2ZfYnl0ZSIgKwogICAgICAic19jb3JkXDAzMFwwMDYgXDAwMShcMDE0QlwwMDJcMDEwXDAwMUhcMDAwXDAyMlwnXG5cMDMxb25lb2Zfc3RyaW5nX3N0cmluIiArCiAgICAgICJnX3BpZWNlXDAzMFwwMDcgXDAwMShcdEJcMDAyXDAxMFwwMDJIXDAwMFwwMjI7XG5cMDMwb25lb2ZfYnl0ZXNfc3RyaW4iICsKICAgICAgImdfcGllY2VcMDMwXDAxMCBcMDAxKFwwMTQ6XDAyM2RlZmF1bHQgU3RyaW5nUGllY2VCXDAwMlwwMTBcMDAySFwwMDAiICsKICAgICAgIlwwMjIxXG5cbm9uZW9mX2VudW1cMDMwXHQgXDAwMShcMDE2MlwwMzMucHJvdG8yX3VuaXR0ZXN0LlYiICsKICAgICAgIjJFbnVtTGl0ZUhcMDAwQlxyXG5cMDEzb25lb2ZfZmllbGRcIlwiXG5cMDIyVGVzdE1lc3NhZyIgKwogICAgICAiZVNldExpdGUqXDAxMFwwMTBkXDAyMFwzNzdcMzc3XDM3N1wzNzdcMDA3OlwwMDJcMDEwXDAwMVwiKlxuXDAxM1BhY2tlZEludDMyXDAyMlwwMzNcbiIgKwogICAgICAiXDAxNnJlcGVhdGVkX2ludDMyXDAzMFwyMDBcMDIwIFwwMDMoXDAwNUJcMDAyXDAyMFwwMDFcIilcblwwMTZOb25QYWNrZWRJIiArCiAgICAgICJudDMyXDAyMlwwMjdcblwwMTZyZXBlYXRlZF9pbnQzMlwwMzBcMjAwXDAyMCBcMDAzKFwwMDVcIi5cblxyUGFja2VkRiIgKwogICAgICAiaXhlZDMyXDAyMlwwMzVcblwwMjByZXBlYXRlZF9maXhlZDMyXDAzMFwyMDBcMDIwIFwwMDMoXDAwN0JcMDAyXDAyMFwwMDFcIi1cbiIgKwogICAgICAiXDAyME5vblBhY2tlZEZpeGVkMzJcMDIyXDAzMVxuXDAyMHJlcGVhdGVkX2ZpeGVkMzJcMDMwXDIwMFwwMjAiICsKICAgICAgIiBcMDAzKFwwMDdcIlpcblwwMDdEdXBFbnVtXCJPXG5cMDMwVGVzdEVudW1XaXRoRHVwVmFsdWVMIiArCiAgICAgICJpdGVcMDIyXDAxMFxuXDAwNEZPTzFcMDIwXDAwMVwwMjJcMDEwXG5cMDA0QkFSMVwwMjBcMDAyXDAyMlwwMDdcblwwMDNCQVpcMDIwXDAwM1wwMjJcMDEwXG5cMDA0Rk9PMiIgKwogICAgICAiXDAyMFwwMDFcMDIyXDAxMFxuXDAwNEJBUjJcMDIwXDAwMlwwMzJcMDAyXDAyMFwwMDFcIldcblwwMjBSZWN1cnNpdmVNZXNzYWdlXDAyMjJcblwwMDciICsKICAgICAgInJlY3Vyc2VcMDMwXDAwMSBcMDAxKFwwMTMyIS5wcm90bzJfdW5pdHRlc3QuUmVjdXJzaXYiICsKICAgICAgImVNZXNzYWdlXDAyMlwwMTdcblwwMDdwYXlsb2FkXDAzMFwwMDIgXDAwMShcMDE0KlNcblwwMTdGb3JlaWduRW51bSIgKwogICAgICAiTGl0ZVwwMjJcMDI0XG5cMDIwRk9SRUlHTl9MSVRFX0ZPT1wwMjBcMDA0XDAyMlwwMjRcblwwMjBGT1JFSUdOX0xJIiArCiAgICAgICJURV9CQVpcMDIwXDAwNlwwMjJcMDI0XG5cMDIwRk9SRUlHTl9MSVRFX0JBUlwwMjBcMDA1KlwwMzJcblxuVjFFbnVtIiArCiAgICAgICJMaXRlXDAyMlwwMTRcblwwMTBWMV9GSVJTVFwwMjBcMDAxKilcblxuVjJFbnVtTGl0ZVwwMjJcMDE0XG5cMDEwVjJfRiIgKwogICAgICAiSVJTVFwwMjBcMDAxXDAyMlxyXG5cdFYyX1NFQ09ORFwwMjBcMDAyOk1cblwwMzVvcHRpb25hbF9pbnQzMl8iICsKICAgICAgImV4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGwiICsKICAgICAgIkV4dGVuc2lvbnNMaXRlXDAzMFwwMDEgXDAwMShcMDA1Ok1cblwwMzVvcHRpb25hbF9pbnQ2NF9lIiArCiAgICAgICJ4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFIiArCiAgICAgICJ4dGVuc2lvbnNMaXRlXDAzMFwwMDIgXDAwMShcMDAzOk5cblwwMzZvcHRpb25hbF91aW50MzJfZSIgKwogICAgICAieHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRSIgKwogICAgICAieHRlbnNpb25zTGl0ZVwwMzBcMDAzIFwwMDEoXHI6TlxuXDAzNm9wdGlvbmFsX3VpbnQ2NF9lIiArCiAgICAgICJ4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFIiArCiAgICAgICJ4dGVuc2lvbnNMaXRlXDAzMFwwMDQgXDAwMShcMDA0Ok5cblwwMzZvcHRpb25hbF9zaW50MzJfZSIgKwogICAgICAieHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRSIgKwogICAgICAieHRlbnNpb25zTGl0ZVwwMzBcMDA1IFwwMDEoXDAyMTpOXG5cMDM2b3B0aW9uYWxfc2ludDY0X2UiICsKICAgICAgInh0ZW5zaW9uX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEUiICsKICAgICAgInh0ZW5zaW9uc0xpdGVcMDMwXDAwNiBcMDAxKFwwMjI6T1xuXDAzN29wdGlvbmFsX2ZpeGVkMzJfIiArCiAgICAgICJleHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsIiArCiAgICAgICJFeHRlbnNpb25zTGl0ZVwwMzBcMDA3IFwwMDEoXDAwNzpPXG5cMDM3b3B0aW9uYWxfZml4ZWQ2NCIgKwogICAgICAiX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbCIgKwogICAgICAibEV4dGVuc2lvbnNMaXRlXDAzMFwwMTAgXDAwMShcMDA2OlBcbiBvcHRpb25hbF9zZml4ZWQiICsKICAgICAgIjMyX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3QiICsKICAgICAgIkFsbEV4dGVuc2lvbnNMaXRlXDAzMFx0IFwwMDEoXDAxNzpQXG4gb3B0aW9uYWxfc2ZpeCIgKwogICAgICAiZWQ2NF9leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZSIgKwogICAgICAic3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcbiBcMDAxKFwwMjA6TVxuXDAzNW9wdGlvbmFsX2ZsIiArCiAgICAgICJvYXRfZXh0ZW5zaW9uX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzIiArCiAgICAgICJ0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwXDAxMyBcMDAxKFwwMDI6TlxuXDAzNm9wdGlvbmFsX2RvdSIgKwogICAgICAiYmxlX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlcyIgKwogICAgICAidEFsbEV4dGVuc2lvbnNMaXRlXDAzMFwwMTQgXDAwMShcMDAxOkxcblwwMzRvcHRpb25hbF9ib28iICsKICAgICAgImxfZXh0ZW5zaW9uX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEEiICsKICAgICAgImxsRXh0ZW5zaW9uc0xpdGVcMDMwXHIgXDAwMShcMDEwOk5cblwwMzZvcHRpb25hbF9zdHJpbiIgKwogICAgICAiZ19leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QSIgKwogICAgICAibGxFeHRlbnNpb25zTGl0ZVwwMzBcMDE2IFwwMDEoXHQ6TVxuXDAzNW9wdGlvbmFsX2J5dGVzIiArCiAgICAgICJfZXh0ZW5zaW9uX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsIiArCiAgICAgICJsRXh0ZW5zaW9uc0xpdGVcMDMwXDAxNyBcMDAxKFwwMTQ6e1xuXDAzNG9wdGlvbmFsZ3JvdXBfZSIgKwogICAgICAieHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRSIgKwogICAgICAieHRlbnNpb25zTGl0ZVwwMzBcMDIwIFwwMDEoXG4yLS5wcm90bzJfdW5pdHRlc3QuT3AiICsKICAgICAgInRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlOlwyMDdcMDAxXG4mb3B0aW9uYWxfIiArCiAgICAgICJuZXN0ZWRfbWVzc2FnZV9leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91IiArCiAgICAgICJuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDIyIFwwMDEoXDAxMzIvLnByIiArCiAgICAgICJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzIiArCiAgICAgICJzYWdlOnxcblwnb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlX2V4dGVuc2kiICsKICAgICAgIm9uX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2kiICsKICAgICAgIm9uc0xpdGVcMDMwXDAyMyBcMDAxKFwwMTMyIy5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk0iICsKICAgICAgImVzc2FnZUxpdGU6XDIwM1wwMDFcbiZvcHRpb25hbF9pbXBvcnRfbWVzc2FnZV9lIiArCiAgICAgICJ4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFIiArCiAgICAgICJ4dGVuc2lvbnNMaXRlXDAzMFwwMjQgXDAwMShcMDEzMisucHJvdG9idWZfdW5pdHRlc3RfIiArCiAgICAgICJpbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGU6XDIwMVwwMDFcbiNvcHRpb25hbF9uZSIgKwogICAgICAic3RlZF9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZSIgKwogICAgICAic3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMFwwMjUgXDAwMShcMDE2MiwucHJvdG8yXyIgKwogICAgICAidW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtOnZcbiQiICsKICAgICAgIm9wdGlvbmFsX2ZvcmVpZ25fZW51bV9leHRlbnNpb25fbGl0ZVwwMjImLnAiICsKICAgICAgInJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDI2IFwwMDEiICsKICAgICAgIihcMDE2MiAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZTp9XG4jIiArCiAgICAgICJvcHRpb25hbF9pbXBvcnRfZW51bV9leHRlbnNpb25fbGl0ZVwwMjImLnByIiArCiAgICAgICJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDI3IFwwMDEoIiArCiAgICAgICJcMDE2MigucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MIiArCiAgICAgICJpdGU6WFxuJG9wdGlvbmFsX3N0cmluZ19waWVjZV9leHRlbnNpb25fbCIgKwogICAgICAiaXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTCIgKwogICAgICAiaXRlXDAzMFwwMzAgXDAwMShcdEJcMDAyXDAxMFwwMDI6TFxuXDAzNG9wdGlvbmFsX2NvcmRfZXh0ZW5zaW9uIiArCiAgICAgICJfbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uIiArCiAgICAgICJzTGl0ZVwwMzBcMDMxIFwwMDEoXHQ6XDIyMFwwMDFcbi1vcHRpb25hbF9wdWJsaWNfaW1wb3J0X20iICsKICAgICAgImVzc2FnZV9leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC4iICsKICAgICAgIlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDMyIFwwMDEoXDAxMzIxLnByb3RvYnVmX3UiICsKICAgICAgIm5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlOlwyMTEiICsKICAgICAgIlwwMDFcbiRvcHRpb25hbF9sYXp5X21lc3NhZ2VfZXh0ZW5zaW9uX2xpdGVcMDIyIiArCiAgICAgICImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwIiArCiAgICAgICJcMDMzIFwwMDEoXDAxMzIvLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIiArCiAgICAgICIuTmVzdGVkTWVzc2FnZUJcMDAyKFwwMDE6XDIyNFwwMDFcbi9vcHRpb25hbF91bnZlcmlmaSIgKwogICAgICAiZWRfbGF6eV9tZXNzYWdlX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yXyIgKwogICAgICAidW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMFwwMzQgXDAwMShcMDEzMi8ucCIgKwogICAgICAicm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZSIgKwogICAgICAic3NhZ2VCXDAwMnhcMDAxOk1cblwwMzVyZXBlYXRlZF9pbnQzMl9leHRlbnNpb25fbGkiICsKICAgICAgInRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGkiICsKICAgICAgInRlXDAzMFwwMzcgXDAwMyhcMDA1Ok1cblwwMzVyZXBlYXRlZF9pbnQ2NF9leHRlbnNpb25fbGl0IiArCiAgICAgICJlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0IiArCiAgICAgICJlXDAzMCAgXDAwMyhcMDAzOk5cblwwMzZyZXBlYXRlZF91aW50MzJfZXh0ZW5zaW9uX2xpdCIgKwogICAgICAiZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdCIgKwogICAgICAiZVwwMzAhIFwwMDMoXHI6TlxuXDAzNnJlcGVhdGVkX3VpbnQ2NF9leHRlbnNpb25fbGl0IiArCiAgICAgICJlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0IiArCiAgICAgICJlXDAzMFwiIFwwMDMoXDAwNDpOXG5cMDM2cmVwZWF0ZWRfc2ludDMyX2V4dGVuc2lvbl9saXQiICsKICAgICAgImVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXQiICsKICAgICAgImVcMDMwIyBcMDAzKFwwMjE6TlxuXDAzNnJlcGVhdGVkX3NpbnQ2NF9leHRlbnNpb25fbGl0IiArCiAgICAgICJlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0IiArCiAgICAgICJlXDAzMCQgXDAwMyhcMDIyOk9cblwwMzdyZXBlYXRlZF9maXhlZDMyX2V4dGVuc2lvbl9saSIgKwogICAgICAidGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaSIgKwogICAgICAidGVcMDMwJSBcMDAzKFwwMDc6T1xuXDAzN3JlcGVhdGVkX2ZpeGVkNjRfZXh0ZW5zaW9uX2wiICsKICAgICAgIml0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0wiICsKICAgICAgIml0ZVwwMzAmIFwwMDMoXDAwNjpQXG4gcmVwZWF0ZWRfc2ZpeGVkMzJfZXh0ZW5zaW9uIiArCiAgICAgICJfbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uIiArCiAgICAgICJzTGl0ZVwwMzBcJyBcMDAzKFwwMTc6UFxuIHJlcGVhdGVkX3NmaXhlZDY0X2V4dGVuc2kiICsKICAgICAgIm9uX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2kiICsKICAgICAgIm9uc0xpdGVcMDMwKCBcMDAzKFwwMjA6TVxuXDAzNXJlcGVhdGVkX2Zsb2F0X2V4dGVuc2lvIiArCiAgICAgICJuX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvIiArCiAgICAgICJuc0xpdGVcMDMwKSBcMDAzKFwwMDI6TlxuXDAzNnJlcGVhdGVkX2RvdWJsZV9leHRlbnNpbyIgKwogICAgICAibl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpbyIgKwogICAgICAibnNMaXRlXDAzMCogXDAwMyhcMDAxOkxcblwwMzRyZXBlYXRlZF9ib29sX2V4dGVuc2lvbl8iICsKICAgICAgImxpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMiICsKICAgICAgIkxpdGVcMDMwKyBcMDAzKFwwMTA6TlxuXDAzNnJlcGVhdGVkX3N0cmluZ19leHRlbnNpb25fIiArCiAgICAgICJsaXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zIiArCiAgICAgICJMaXRlXDAzMCwgXDAwMyhcdDpNXG5cMDM1cmVwZWF0ZWRfYnl0ZXNfZXh0ZW5zaW9uX2wiICsKICAgICAgIml0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0wiICsKICAgICAgIml0ZVwwMzAtIFwwMDMoXDAxNDp7XG5cMDM0cmVwZWF0ZWRncm91cF9leHRlbnNpb25fbGl0IiArCiAgICAgICJlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0IiArCiAgICAgICJlXDAzMC4gXDAwMyhcbjItLnByb3RvMl91bml0dGVzdC5SZXBlYXRlZEdyb3VwXyIgKwogICAgICAiZXh0ZW5zaW9uX2xpdGU6XDIwN1wwMDFcbiZyZXBlYXRlZF9uZXN0ZWRfbWVzc2EiICsKICAgICAgImdlX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3QiICsKICAgICAgIkFsbEV4dGVuc2lvbnNMaXRlXDAzMDAgXDAwMyhcMDEzMi8ucHJvdG8yX3VuaXR0ZXMiICsKICAgICAgInQuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlOnxcblwncmVwZSIgKwogICAgICAiYXRlZF9mb3JlaWduX21lc3NhZ2VfZXh0ZW5zaW9uX2xpdGVcMDIyJi5wciIgKwogICAgICAib3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwMSBcMDAzKCIgKwogICAgICAiXDAxMzIjLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGU6XDIwMyIgKwogICAgICAiXDAwMVxuJnJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlX2V4dGVuc2lvbl9saXQiICsKICAgICAgImVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXQiICsKICAgICAgImVcMDMwMiBcMDAzKFwwMTMyKy5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3IiICsKICAgICAgInRNZXNzYWdlTGl0ZTpcMjAxXDAwMVxuI3JlcGVhdGVkX25lc3RlZF9lbnVtX2V4IiArCiAgICAgICJ0ZW5zaW9uX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4IiArCiAgICAgICJ0ZW5zaW9uc0xpdGVcMDMwMyBcMDAzKFwwMTYyLC5wcm90bzJfdW5pdHRlc3QuVGVzIiArCiAgICAgICJ0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW06dlxuJHJlcGVhdGVkX2ZvciIgKwogICAgICAiZWlnbl9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZSIgKwogICAgICAic3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMDQgXDAwMyhcMDE2MiAucHJvdG8yXyIgKwogICAgICAidW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlOn1cbiNyZXBlYXRlZF9pbXAiICsKICAgICAgIm9ydF9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXMiICsKICAgICAgInQuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMDUgXDAwMyhcMDE2MigucHJvdG9idWYiICsKICAgICAgIl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGU6WFxuJHJlcGVhIiArCiAgICAgICJ0ZWRfc3RyaW5nX3BpZWNlX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yIiArCiAgICAgICJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMDYgXDAwMyhcdEJcMDAyXDAxMCIgKwogICAgICAiXDAwMjpMXG5cMDM0cmVwZWF0ZWRfY29yZF9leHRlbnNpb25fbGl0ZVwwMjImLnByb3QiICsKICAgICAgIm8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzA3IFwwMDMoXHQ6IiArCiAgICAgICJcMjExXDAwMVxuJHJlcGVhdGVkX2xhenlfbWVzc2FnZV9leHRlbnNpb25fbGl0ZSIgKwogICAgICAiXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSIgKwogICAgICAiXDAzMDkgXDAwMyhcMDEzMi8ucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdCIgKwogICAgICAiZS5OZXN0ZWRNZXNzYWdlQlwwMDIoXDAwMTpQXG5cMDM0ZGVmYXVsdF9pbnQzMl9leHQiICsKICAgICAgImVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHQiICsKICAgICAgImVuc2lvbnNMaXRlXDAzMD0gXDAwMShcMDA1OlwwMDI0MTpQXG5cMDM0ZGVmYXVsdF9pbnQ2NF9lIiArCiAgICAgICJ4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFIiArCiAgICAgICJ4dGVuc2lvbnNMaXRlXDAzMD4gXDAwMShcMDAzOlwwMDI0MjpRXG5cMDM1ZGVmYXVsdF91aW50MyIgKwogICAgICAiMl9leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QSIgKwogICAgICAibGxFeHRlbnNpb25zTGl0ZVwwMzA/IFwwMDEoXHI6XDAwMjQzOlFcblwwMzVkZWZhdWx0X3VpIiArCiAgICAgICJudDY0X2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlIiArCiAgICAgICJzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMEAgXDAwMShcMDA0OlwwMDI0NDpSXG5cMDM1ZGVmYXVsdCIgKwogICAgICAiX3NpbnQzMl9leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdCIgKwogICAgICAiLlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBBIFwwMDEoXDAyMTpcMDAzLTQ1OlFcblwwMzVkZWYiICsKICAgICAgImF1bHRfc2ludDY0X2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXQiICsKICAgICAgInRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMEIgXDAwMShcMDIyOlwwMDI0NjpSXG5cMDM2IiArCiAgICAgICJkZWZhdWx0X2ZpeGVkMzJfZXh0ZW5zaW9uX2xpdGVcMDIyJi5wcm90bzJfIiArCiAgICAgICJ1bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwQyBcMDAxKFwwMDc6XDAwMjQ3IiArCiAgICAgICI6UlxuXDAzNmRlZmF1bHRfZml4ZWQ2NF9leHRlbnNpb25fbGl0ZVwwMjImLnBybyIgKwogICAgICAidG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBEIFwwMDEoXDAwNiIgKwogICAgICAiOlwwMDI0ODpTXG5cMDM3ZGVmYXVsdF9zZml4ZWQzMl9leHRlbnNpb25fbGl0ZVwwMjIiICsKICAgICAgIiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzAiICsKICAgICAgIkUgXDAwMShcMDE3OlwwMDI0OTpUXG5cMDM3ZGVmYXVsdF9zZml4ZWQ2NF9leHRlbnNpb25fIiArCiAgICAgICJsaXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zIiArCiAgICAgICJMaXRlXDAzMEYgXDAwMShcMDIwOlwwMDMtNTA6UlxuXDAzNGRlZmF1bHRfZmxvYXRfZXh0ZW5zaSIgKwogICAgICAib25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaSIgKwogICAgICAib25zTGl0ZVwwMzBHIFwwMDEoXDAwMjpcMDA0NTEuNTpUXG5cMDM1ZGVmYXVsdF9kb3VibGVfZXgiICsKICAgICAgInRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXgiICsKICAgICAgInRlbnNpb25zTGl0ZVwwMzBIIFwwMDEoXDAwMTpcMDA1NTIwMDA6UVxuXDAzM2RlZmF1bHRfYm9vIiArCiAgICAgICJsX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LlRlc3RBIiArCiAgICAgICJsbEV4dGVuc2lvbnNMaXRlXDAzMEkgXDAwMShcMDEwOlwwMDR0cnVlOlRcblwwMzVkZWZhdWx0XyIgKwogICAgICAic3RyaW5nX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0LiIgKwogICAgICAiVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMEogXDAwMShcdDpcMDA1aGVsbG86U1xuXDAzNGRlIiArCiAgICAgICJmYXVsdF9ieXRlc19leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0IiArCiAgICAgICJ0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBLIFwwMDEoXDAxNDpcMDA1d29ybGQ6IiArCiAgICAgICJcMjA1XDAwMVxuXCJkZWZhdWx0X25lc3RlZF9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMiYiICsKICAgICAgIi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMFEiICsKICAgICAgIiBcMDAxKFwwMTYyLC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS4iICsKICAgICAgIk5lc3RlZEVudW06XDAwM0JBUjpcMjA3XDAwMVxuI2RlZmF1bHRfZm9yZWlnbl9lbnVtIiArCiAgICAgICJfZXh0ZW5zaW9uX2xpdGVcMDIyJi5wcm90bzJfdW5pdHRlc3QuVGVzdEFsIiArCiAgICAgICJsRXh0ZW5zaW9uc0xpdGVcMDMwUiBcMDAxKFwwMTYyIC5wcm90bzJfdW5pdHRlc3QuIiArCiAgICAgICJGb3JlaWduRW51bUxpdGU6XDAyMEZPUkVJR05fTElURV9CQVI6XDIxNVwwMDFcblwiZGUiICsKICAgICAgImZhdWx0X2ltcG9ydF9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8iICsKICAgICAgIjJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMFMgXDAwMShcMDE2MigiICsKICAgICAgIi5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUiICsKICAgICAgIjpcMDE3SU1QT1JUX0xJVEVfQkFSOlxcXG4jZGVmYXVsdF9zdHJpbmdfcGllYyIgKwogICAgICAiZV9leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGVzdC5UZXN0QSIgKwogICAgICAibGxFeHRlbnNpb25zTGl0ZVwwMzBUIFwwMDEoXHQ6XDAwM2FiY0JcMDAyXDAxMFwwMDI6UFxuXDAzM2RlZmF1IiArCiAgICAgICJsdF9jb3JkX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yX3VuaXR0ZXN0IiArCiAgICAgICIuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMFUgXDAwMShcdDpcMDAzMTIzOktcblwwMzNvbmUiICsKICAgICAgIm9mX3VpbnQzMl9leHRlbnNpb25fbGl0ZVwwMjImLnByb3RvMl91bml0dGUiICsKICAgICAgInN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBvIFwwMDEoXHI6XDIwNFwwMDFcbiNvbmVvZiIgKwogICAgICAiX25lc3RlZF9tZXNzYWdlX2V4dGVuc2lvbl9saXRlXDAyMiYucHJvdG8yXyIgKwogICAgICAidW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMHAgXDAwMShcMDEzMi8ucCIgKwogICAgICAicm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZSIgKwogICAgICAic3NhZ2U6S1xuXDAzM29uZW9mX3N0cmluZ19leHRlbnNpb25fbGl0ZVwwMjImLnAiICsKICAgICAgInJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBxIFwwMDEiICsKICAgICAgIihcdDpKXG5cMDMyb25lb2ZfYnl0ZXNfZXh0ZW5zaW9uX2xpdGVcMDIyJi5wcm90byIgKwogICAgICAiMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwciBcMDAxKFwwMTQ6UiIgKwogICAgICAiXG5cMDMzcGFja2VkX2ludDMyX2V4dGVuc2lvbl9saXRlXDAyMikucHJvdG8yX3UiICsKICAgICAgIm5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlXDAzMFogXDAwMyhcMDA1QlwwMDIiICsKICAgICAgIlwwMjBcMDAxOlJcblwwMzNwYWNrZWRfaW50NjRfZXh0ZW5zaW9uX2xpdGVcMDIyKS5wcm90IiArCiAgICAgICJvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVcMDMwWyBcMDAzIiArCiAgICAgICIoXDAwM0JcMDAyXDAyMFwwMDE6U1xuXDAzNHBhY2tlZF91aW50MzJfZXh0ZW5zaW9uX2xpdGVcMDIyKSIgKwogICAgICAiLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdCIgKwogICAgICAiZVwwMzBcXCBcMDAzKFxyQlwwMDJcMDIwXDAwMTpTXG5cMDM0cGFja2VkX3VpbnQ2NF9leHRlbnNpb25fbCIgKwogICAgICAiaXRlXDAyMikucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpbyIgKwogICAgICAibnNMaXRlXDAzMF0gXDAwMyhcMDA0QlwwMDJcMDIwXDAwMTpTXG5cMDM0cGFja2VkX3NpbnQzMl9leHRlbnMiICsKICAgICAgImlvbl9saXRlXDAyMikucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHQiICsKICAgICAgImVuc2lvbnNMaXRlXDAzMF4gXDAwMyhcMDIxQlwwMDJcMDIwXDAwMTpTXG5cMDM0cGFja2VkX3NpbnQ2NF9lIiArCiAgICAgICJ4dGVuc2lvbl9saXRlXDAyMikucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrIiArCiAgICAgICJlZEV4dGVuc2lvbnNMaXRlXDAzMF8gXDAwMyhcMDIyQlwwMDJcMDIwXDAwMTpUXG5cMDM1cGFja2VkX2ZpeCIgKwogICAgICAiZWQzMl9leHRlbnNpb25fbGl0ZVwwMjIpLnByb3RvMl91bml0dGVzdC5UZSIgKwogICAgICAic3RQYWNrZWRFeHRlbnNpb25zTGl0ZVwwMzBgIFwwMDMoXDAwN0JcMDAyXDAyMFwwMDE6VFxuXDAzNXBhY2siICsKICAgICAgImVkX2ZpeGVkNjRfZXh0ZW5zaW9uX2xpdGVcMDIyKS5wcm90bzJfdW5pdHQiLAogICAgICAiZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZVwwMzBhIFwwMDMoXDAwNkJcMDAyXDAyMFwwMDE6VSIgKwogICAgICAiXG5cMDM2cGFja2VkX3NmaXhlZDMyX2V4dGVuc2lvbl9saXRlXDAyMikucHJvdG8iICsKICAgICAgIjJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlXDAzMGIgXDAwMygiICsKICAgICAgIlwwMTdCXDAwMlwwMjBcMDAxOlVcblwwMzZwYWNrZWRfc2ZpeGVkNjRfZXh0ZW5zaW9uX2xpdGVcMDIyIiArCiAgICAgICIpLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpIiArCiAgICAgICJ0ZVwwMzBjIFwwMDMoXDAyMEJcMDAyXDAyMFwwMDE6UlxuXDAzM3BhY2tlZF9mbG9hdF9leHRlbnNpb25fbCIgKwogICAgICAiaXRlXDAyMikucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpbyIgKwogICAgICAibnNMaXRlXDAzMGQgXDAwMyhcMDAyQlwwMDJcMDIwXDAwMTpTXG5cMDM0cGFja2VkX2RvdWJsZV9leHRlbnMiICsKICAgICAgImlvbl9saXRlXDAyMikucHJvdG8yX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHQiICsKICAgICAgImVuc2lvbnNMaXRlXDAzMGUgXDAwMyhcMDAxQlwwMDJcMDIwXDAwMTpRXG5cMDMycGFja2VkX2Jvb2xfZXh0IiArCiAgICAgICJlbnNpb25fbGl0ZVwwMjIpLnByb3RvMl91bml0dGVzdC5UZXN0UGFja2VkIiArCiAgICAgICJFeHRlbnNpb25zTGl0ZVwwMzBmIFwwMDMoXDAxMEJcMDAyXDAyMFwwMDE6c1xuXDAzMnBhY2tlZF9lbnVtXyIgKwogICAgICAiZXh0ZW5zaW9uX2xpdGVcMDIyKS5wcm90bzJfdW5pdHRlc3QuVGVzdFBhYyIgKwogICAgICAia2VkRXh0ZW5zaW9uc0xpdGVcMDMwZyBcMDAzKFwwMTYyIC5wcm90bzJfdW5pdHRlcyIgKwogICAgICAidC5Gb3JlaWduRW51bUxpdGVCXDAwMlwwMjBcMDAxOm1cblwwMjN0ZXN0X2FsbF90eXBlc18iICsKICAgICAgImxpdGVcMDIyKS5wcm90bzJfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWIiICsKICAgICAgImVyc0xpdGVcMDMwXDM0MFwyNTJcMzc3XDM3N1wwMDEgXDAwMShcMDEzMiEucHJvdG8yX3VuaXR0ZXN0LlRlc3QiICsKICAgICAgIkFsbFR5cGVzTGl0ZUJcMDMyXG5cMDIzY29tLmdvb2dsZS5wcm90b2J1ZkhcMDAzXDM3MFwwMDFcMDAxIgogICAgfTsKICAgIGRlc2NyaXB0b3IgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIC5pbnRlcm5hbEJ1aWxkR2VuZXJhdGVkRmlsZUZyb20oZGVzY3JpcHRvckRhdGEsCiAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3JbXSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5nZXREZXNjcmlwdG9yKCksCiAgICAgICAgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIk9wdGlvbmFsSW50MzIiLCAiT3B0aW9uYWxJbnQ2NCIsICJPcHRpb25hbFVpbnQzMiIsICJPcHRpb25hbFVpbnQ2NCIsICJPcHRpb25hbFNpbnQzMiIsICJPcHRpb25hbFNpbnQ2NCIsICJPcHRpb25hbEZpeGVkMzIiLCAiT3B0aW9uYWxGaXhlZDY0IiwgIk9wdGlvbmFsU2ZpeGVkMzIiLCAiT3B0aW9uYWxTZml4ZWQ2NCIsICJPcHRpb25hbEZsb2F0IiwgIk9wdGlvbmFsRG91YmxlIiwgIk9wdGlvbmFsQm9vbCIsICJPcHRpb25hbFN0cmluZyIsICJPcHRpb25hbEJ5dGVzIiwgIk9wdGlvbmFsR3JvdXAiLCAiT3B0aW9uYWxOZXN0ZWRNZXNzYWdlIiwgIk9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UiLCAiT3B0aW9uYWxJbXBvcnRNZXNzYWdlIiwgIk9wdGlvbmFsTmVzdGVkRW51bSIsICJPcHRpb25hbEZvcmVpZ25FbnVtIiwgIk9wdGlvbmFsSW1wb3J0RW51bSIsICJPcHRpb25hbFN0cmluZ1BpZWNlIiwgIk9wdGlvbmFsQ29yZCIsICJPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UiLCAiT3B0aW9uYWxMYXp5TWVzc2FnZSIsICJPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSIsICJSZXBlYXRlZEludDMyIiwgIlJlcGVhdGVkSW50NjQiLCAiUmVwZWF0ZWRVaW50MzIiLCAiUmVwZWF0ZWRVaW50NjQiLCAiUmVwZWF0ZWRTaW50MzIiLCAiUmVwZWF0ZWRTaW50NjQiLCAiUmVwZWF0ZWRGaXhlZDMyIiwgIlJlcGVhdGVkRml4ZWQ2NCIsICJSZXBlYXRlZFNmaXhlZDMyIiwgIlJlcGVhdGVkU2ZpeGVkNjQiLCAiUmVwZWF0ZWRGbG9hdCIsICJSZXBlYXRlZERvdWJsZSIsICJSZXBlYXRlZEJvb2wiLCAiUmVwZWF0ZWRTdHJpbmciLCAiUmVwZWF0ZWRCeXRlcyIsICJSZXBlYXRlZEdyb3VwIiwgIlJlcGVhdGVkTmVzdGVkTWVzc2FnZSIsICJSZXBlYXRlZEZvcmVpZ25NZXNzYWdlIiwgIlJlcGVhdGVkSW1wb3J0TWVzc2FnZSIsICJSZXBlYXRlZE5lc3RlZEVudW0iLCAiUmVwZWF0ZWRGb3JlaWduRW51bSIsICJSZXBlYXRlZEltcG9ydEVudW0iLCAiUmVwZWF0ZWRTdHJpbmdQaWVjZSIsICJSZXBlYXRlZENvcmQiLCAiUmVwZWF0ZWRMYXp5TWVzc2FnZSIsICJEZWZhdWx0SW50MzIiLCAiRGVmYXVsdEludDY0IiwgIkRlZmF1bHRVaW50MzIiLCAiRGVmYXVsdFVpbnQ2NCIsICJEZWZhdWx0U2ludDMyIiwgIkRlZmF1bHRTaW50NjQiLCAiRGVmYXVsdEZpeGVkMzIiLCAiRGVmYXVsdEZpeGVkNjQiLCAiRGVmYXVsdFNmaXhlZDMyIiwgIkRlZmF1bHRTZml4ZWQ2NCIsICJEZWZhdWx0RmxvYXQiLCAiRGVmYXVsdERvdWJsZSIsICJEZWZhdWx0Qm9vbCIsICJEZWZhdWx0U3RyaW5nIiwgIkRlZmF1bHRCeXRlcyIsICJEZWZhdWx0TmVzdGVkRW51bSIsICJEZWZhdWx0Rm9yZWlnbkVudW0iLCAiRGVmYXVsdEltcG9ydEVudW0iLCAiRGVmYXVsdFN0cmluZ1BpZWNlIiwgIkRlZmF1bHRDb3JkIiwgIk9uZW9mVWludDMyIiwgIk9uZW9mTmVzdGVkTWVzc2FnZSIsICJPbmVvZlN0cmluZyIsICJPbmVvZkJ5dGVzIiwgIk9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UiLCAiT25lb2ZOZXN0ZWRNZXNzYWdlMiIsICJEZWNlcHRpdmVseU5hbWVkTGlzdCIsICJPbmVvZkZpZWxkIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJCYiIsICJDYyIsICJEZCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2UyX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlMl9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlMl9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiRGQiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgyKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9PcHRpb25hbEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkEiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgzKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9SZXBlYXRlZEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX1JlcGVhdGVkR3JvdXBfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkEiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDEpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiQyIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDIpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJQYWNrZWRJbnQzMiIsICJQYWNrZWRJbnQ2NCIsICJQYWNrZWRVaW50MzIiLCAiUGFja2VkVWludDY0IiwgIlBhY2tlZFNpbnQzMiIsICJQYWNrZWRTaW50NjQiLCAiUGFja2VkRml4ZWQzMiIsICJQYWNrZWRGaXhlZDY0IiwgIlBhY2tlZFNmaXhlZDMyIiwgIlBhY2tlZFNmaXhlZDY0IiwgIlBhY2tlZEZsb2F0IiwgIlBhY2tlZERvdWJsZSIsICJQYWNrZWRCb29sIiwgIlBhY2tlZEVudW0iLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFsbEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDMpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBbGxFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg0KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiQSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDUpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJBIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg2KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3ROZXN0ZWRFeHRlbnNpb25MaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDcpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3REZXByZWNhdGVkTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg4KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdERlcHJlY2F0ZWRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkRlcHJlY2F0ZWRGaWVsZCIsICJEZXByZWNhdGVkRmllbGQyIiwgIkRlcHJlY2F0ZWRGaWVsZDMiLCAiRGVwcmVjYXRlZEZpZWxkNCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg5KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJSZXF1aXJlZEFsbFR5cGVzIiwgIk9wdGlvbmFsQWxsVHlwZXMiLCAiUmVwZWF0ZWRBbGxUeXBlcyIsICJPcHRpb25hbEdyb3VwIiwgIlJlcGVhdGVkR3JvdXAiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJGaWVsZDEiLCAiRmllbGQyIiwgIkZpZWxkMyIsICJHcm91cDEiLCAiR3JvdXAyIiwgIkV4dDEiLCAiRXh0MiIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDFfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAxX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDFfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkZpZWxkMSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDJfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAyX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDJfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkZpZWxkMSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX09wdGlvbmFsR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIk9wdGlvbmFsR3JvdXBBbGxUeXBlcyIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMik7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkR3JvdXBfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlJlcGVhdGVkR3JvdXBBbGxUeXBlcyIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVyZ2VFeGNlcHRpb25MaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDEwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiQWxsRXh0ZW5zaW9ucyIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgxMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgxMik7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YxTWVzc2FnZUxpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTMpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9WMU1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9WMU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJJbnRGaWVsZCIsICJFbnVtRmllbGQiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVjJNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgxNCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkludEZpZWxkIiwgIkVudW1GaWVsZCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTUpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiT3B0aW9uYWxJbnQzMiIsICJGaXhlZDMyIiwgIlJlcGVhdGVkSW50MzIiLCAiUGFja2VkSW50MzIiLCAiT3B0aW9uYWxFbnVtIiwgIk9wdGlvbmFsU3RyaW5nIiwgIk9wdGlvbmFsQnl0ZXMiLCAiT3B0aW9uYWxNZXNzYWdlIiwgIk9wdGlvbmFsR3JvdXAiLCAiU3RyaW5nU3RyaW5nTWFwIiwgIk9uZW9mVWludDMyIiwgIk9uZW9mVGVzdEFsbFR5cGVzIiwgIk9uZW9mU3RyaW5nIiwgIk9uZW9mQnl0ZXMiLCAiT25lb2ZGaWVsZCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX09wdGlvbmFsR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJHcm91cEEiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX1N0cmluZ1N0cmluZ01hcEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDEpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfU3RyaW5nU3RyaW5nTWFwRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9TdHJpbmdTdHJpbmdNYXBFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RPbmVvZlBhcnNpbmdMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDE2KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE9uZW9mUGFyc2luZ0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RPbmVvZlBhcnNpbmdMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJPbmVvZkludDMyIiwgIk9uZW9mU3VibWVzc2FnZSIsICJPbmVvZlN0cmluZyIsICJPbmVvZkJ5dGVzIiwgIk9uZW9mU3RyaW5nQ29yZCIsICJPbmVvZkJ5dGVzQ29yZCIsICJPbmVvZlN0cmluZ1N0cmluZ1BpZWNlIiwgIk9uZW9mQnl0ZXNTdHJpbmdQaWVjZSIsICJPbmVvZkVudW0iLCAiT25lb2ZGaWVsZCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVzc2FnZVNldExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTcpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVzc2FnZVNldExpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlU2V0TGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkSW50MzJfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTgpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9QYWNrZWRJbnQzMl9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkSW50MzJfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlJlcGVhdGVkSW50MzIiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkSW50MzJfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTkpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Ob25QYWNrZWRJbnQzMl9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkSW50MzJfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlJlcGVhdGVkSW50MzIiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgyMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1BhY2tlZEZpeGVkMzJfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1BhY2tlZEZpeGVkMzJfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlJlcGVhdGVkRml4ZWQzMiIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Ob25QYWNrZWRGaXhlZDMyX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDIxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiUmVwZWF0ZWRGaXhlZDMyIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X0R1cEVudW1fZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMjIpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9EdXBFbnVtX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9EdXBFbnVtX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7IH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDIzKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVjdXJzaXZlTWVzc2FnZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfUmVjdXJzaXZlTWVzc2FnZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiUmVjdXJzZSIsICJQYXlsb2FkIiwgfSk7CiAgICBvcHRpb25hbEludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDApKTsKICAgIG9wdGlvbmFsSW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMSkpOwogICAgb3B0aW9uYWxVaW50MzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMikpOwogICAgb3B0aW9uYWxVaW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMykpOwogICAgb3B0aW9uYWxTaW50MzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNCkpOwogICAgb3B0aW9uYWxTaW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNSkpOwogICAgb3B0aW9uYWxGaXhlZDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDYpKTsKICAgIG9wdGlvbmFsRml4ZWQ2NEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg3KSk7CiAgICBvcHRpb25hbFNmaXhlZDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDgpKTsKICAgIG9wdGlvbmFsU2ZpeGVkNjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoOSkpOwogICAgb3B0aW9uYWxGbG9hdEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgxMCkpOwogICAgb3B0aW9uYWxEb3VibGVFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTEpKTsKICAgIG9wdGlvbmFsQm9vbEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgxMikpOwogICAgb3B0aW9uYWxTdHJpbmdFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTMpKTsKICAgIG9wdGlvbmFsQnl0ZXNFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTQpKTsKICAgIG9wdGlvbmFsR3JvdXBFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTUpKTsKICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgxNikpOwogICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgxNykpOwogICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDE4KSk7CiAgICBvcHRpb25hbE5lc3RlZEVudW1FeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTkpKTsKICAgIG9wdGlvbmFsRm9yZWlnbkVudW1FeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMjApKTsKICAgIG9wdGlvbmFsSW1wb3J0RW51bUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgyMSkpOwogICAgb3B0aW9uYWxTdHJpbmdQaWVjZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgyMikpOwogICAgb3B0aW9uYWxDb3JkRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDIzKSk7CiAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMjQpKTsKICAgIG9wdGlvbmFsTGF6eU1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMjUpKTsKICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDI2KSk7CiAgICByZXBlYXRlZEludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDI3KSk7CiAgICByZXBlYXRlZEludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDI4KSk7CiAgICByZXBlYXRlZFVpbnQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgyOSkpOwogICAgcmVwZWF0ZWRVaW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMzApKTsKICAgIHJlcGVhdGVkU2ludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDMxKSk7CiAgICByZXBlYXRlZFNpbnQ2NEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgzMikpOwogICAgcmVwZWF0ZWRGaXhlZDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDMzKSk7CiAgICByZXBlYXRlZEZpeGVkNjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMzQpKTsKICAgIHJlcGVhdGVkU2ZpeGVkMzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMzUpKTsKICAgIHJlcGVhdGVkU2ZpeGVkNjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMzYpKTsKICAgIHJlcGVhdGVkRmxvYXRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMzcpKTsKICAgIHJlcGVhdGVkRG91YmxlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDM4KSk7CiAgICByZXBlYXRlZEJvb2xFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMzkpKTsKICAgIHJlcGVhdGVkU3RyaW5nRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQwKSk7CiAgICByZXBlYXRlZEJ5dGVzRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQxKSk7CiAgICByZXBlYXRlZEdyb3VwRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQyKSk7CiAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNDMpKTsKICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNDQpKTsKICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg0NSkpOwogICAgcmVwZWF0ZWROZXN0ZWRFbnVtRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQ2KSk7CiAgICByZXBlYXRlZEZvcmVpZ25FbnVtRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQ3KSk7CiAgICByZXBlYXRlZEltcG9ydEVudW1FeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNDgpKTsKICAgIHJlcGVhdGVkU3RyaW5nUGllY2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNDkpKTsKICAgIHJlcGVhdGVkQ29yZEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg1MCkpOwogICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg1MSkpOwogICAgZGVmYXVsdEludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDUyKSk7CiAgICBkZWZhdWx0SW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNTMpKTsKICAgIGRlZmF1bHRVaW50MzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNTQpKTsKICAgIGRlZmF1bHRVaW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNTUpKTsKICAgIGRlZmF1bHRTaW50MzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNTYpKTsKICAgIGRlZmF1bHRTaW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNTcpKTsKICAgIGRlZmF1bHRGaXhlZDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDU4KSk7CiAgICBkZWZhdWx0Rml4ZWQ2NEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg1OSkpOwogICAgZGVmYXVsdFNmaXhlZDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDYwKSk7CiAgICBkZWZhdWx0U2ZpeGVkNjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjEpKTsKICAgIGRlZmF1bHRGbG9hdEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg2MikpOwogICAgZGVmYXVsdERvdWJsZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg2MykpOwogICAgZGVmYXVsdEJvb2xFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjQpKTsKICAgIGRlZmF1bHRTdHJpbmdFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjUpKTsKICAgIGRlZmF1bHRCeXRlc0V4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg2NikpOwogICAgZGVmYXVsdE5lc3RlZEVudW1FeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjcpKTsKICAgIGRlZmF1bHRGb3JlaWduRW51bUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg2OCkpOwogICAgZGVmYXVsdEltcG9ydEVudW1FeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjkpKTsKICAgIGRlZmF1bHRTdHJpbmdQaWVjZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg3MCkpOwogICAgZGVmYXVsdENvcmRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNzEpKTsKICAgIG9uZW9mVWludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDcyKSk7CiAgICBvbmVvZk5lc3RlZE1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNzMpKTsKICAgIG9uZW9mU3RyaW5nRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDc0KSk7CiAgICBvbmVvZkJ5dGVzRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDc1KSk7CiAgICBwYWNrZWRJbnQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg3NikpOwogICAgcGFja2VkSW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNzcpKTsKICAgIHBhY2tlZFVpbnQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg3OCkpOwogICAgcGFja2VkVWludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDc5KSk7CiAgICBwYWNrZWRTaW50MzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoODApKTsKICAgIHBhY2tlZFNpbnQ2NEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4MSkpOwogICAgcGFja2VkRml4ZWQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4MikpOwogICAgcGFja2VkRml4ZWQ2NEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4MykpOwogICAgcGFja2VkU2ZpeGVkMzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoODQpKTsKICAgIHBhY2tlZFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDg1KSk7CiAgICBwYWNrZWRGbG9hdEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4NikpOwogICAgcGFja2VkRG91YmxlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDg3KSk7CiAgICBwYWNrZWRCb29sRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDg4KSk7CiAgICBwYWNrZWRFbnVtRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDg5KSk7CiAgICB0ZXN0QWxsVHlwZXNMaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoOTApKTsKICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLmdldERlc2NyaXB0b3IoKTsKICB9CgogIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChvdXRlcl9jbGFzc19zY29wZSkKfQpQSwMECgAAAAAAAAAhAODGdYZI9QkASPUJACQAAABwcm90bzJfdW5pdHRlc3QvTWFwTGl0ZVVuaXR0ZXN0LmphdmEvLyBHZW5lcmF0ZWQgYnkgdGhlIHByb3RvY29sIGJ1ZmZlciBjb21waWxlci4gIERPIE5PVCBFRElUIQovLyBzb3VyY2U6IGdvb2dsZS9wcm90b2J1Zi9tYXBfbGl0ZV91bml0dGVzdC5wcm90bwoKLy8gUHJvdG9idWYgSmF2YSBWZXJzaW9uOiAzLjI1LjAKcGFja2FnZSBwcm90bzJfdW5pdHRlc3Q7CgpwdWJsaWMgZmluYWwgY2xhc3MgTWFwTGl0ZVVuaXR0ZXN0IHsKICBwcml2YXRlIE1hcExpdGVVbml0dGVzdCgpIHt9CiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgcmVnaXN0cnkpIHsKICAgIHJlZ2lzdHJ5LmFkZChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuc2luZ2xlKTsKICB9CgogIHB1YmxpYyBzdGF0aWMgdm9pZCByZWdpc3RlckFsbEV4dGVuc2lvbnMoCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnkgcmVnaXN0cnkpIHsKICAgIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUpIHJlZ2lzdHJ5KTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgZW51bSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlfQogICAqLwogIHB1YmxpYyBlbnVtIFByb3RvMk1hcEVudW1MaXRlCiAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Qcm90b2NvbE1lc3NhZ2VFbnVtIHsKICAgIC8qKgogICAgICogPGNvZGU+UFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFID0gMDs8L2NvZGU+CiAgICAgKi8KICAgIFBST1RPMl9NQVBfRU5VTV9GT09fTElURSgwKSwKICAgIC8qKgogICAgICogPGNvZGU+UFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIFBST1RPMl9NQVBfRU5VTV9CQVJfTElURSgxKSwKICAgIC8qKgogICAgICogPGNvZGU+UFJPVE8yX01BUF9FTlVNX0JBWl9MSVRFID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIFBST1RPMl9NQVBfRU5VTV9CQVpfTElURSgyKSwKICAgIDsKCiAgICAvKioKICAgICAqIDxjb2RlPlBST1RPMl9NQVBfRU5VTV9GT09fTElURSA9IDA7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEVfVkFMVUUgPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5QUk9UTzJfTUFQX0VOVU1fQkFSX0xJVEUgPSAxOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFX1ZBTFVFID0gMTsKICAgIC8qKgogICAgICogPGNvZGU+UFJPVE8yX01BUF9FTlVNX0JBWl9MSVRFID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBST1RPMl9NQVBfRU5VTV9CQVpfTElURV9WQUxVRSA9IDI7CgoKICAgIHB1YmxpYyBmaW5hbCBpbnQgZ2V0TnVtYmVyKCkgewogICAgICByZXR1cm4gdmFsdWU7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgI2Zvck51bWJlcihpbnQpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBzdGF0aWMgUHJvdG8yTWFwRW51bUxpdGUgdmFsdWVPZihpbnQgdmFsdWUpIHsKICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBQcm90bzJNYXBFbnVtTGl0ZSBmb3JOdW1iZXIoaW50IHZhbHVlKSB7CiAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICBjYXNlIDA6IHJldHVybiBQUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEU7CiAgICAgICAgY2FzZSAxOiByZXR1cm4gUFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFOwogICAgICAgIGNhc2UgMjogcmV0dXJuIFBST1RPMl9NQVBfRU5VTV9CQVpfTElURTsKICAgICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxQcm90bzJNYXBFbnVtTGl0ZT4KICAgICAgICBpbnRlcm5hbEdldFZhbHVlTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxWYWx1ZU1hcDsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8CiAgICAgICAgUHJvdG8yTWFwRW51bUxpdGU+IGludGVybmFsVmFsdWVNYXAgPQogICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8UHJvdG8yTWFwRW51bUxpdGU+KCkgewogICAgICAgICAgICBwdWJsaWMgUHJvdG8yTWFwRW51bUxpdGUgZmluZFZhbHVlQnlOdW1iZXIoaW50IG51bWJlcikgewogICAgICAgICAgICAgIHJldHVybiBQcm90bzJNYXBFbnVtTGl0ZS5mb3JOdW1iZXIobnVtYmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKCiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yCiAgICAgICAgZ2V0VmFsdWVEZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpLmdldFZhbHVlcygpLmdldChvcmRpbmFsKCkpOwogICAgfQogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMCk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgUHJvdG8yTWFwRW51bUxpdGVbXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICBwdWJsaWMgc3RhdGljIFByb3RvMk1hcEVudW1MaXRlIHZhbHVlT2YoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yIGRlc2MpIHsKICAgICAgaWYgKGRlc2MuZ2V0VHlwZSgpICE9IGdldERlc2NyaXB0b3IoKSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKAogICAgICAgICAgIkVudW1WYWx1ZURlc2NyaXB0b3IgaXMgbm90IGZvciB0aGlzIHR5cGUuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIFZBTFVFU1tkZXNjLmdldEluZGV4KCldOwogICAgfQoKICAgIHByaXZhdGUgZmluYWwgaW50IHZhbHVlOwoKICAgIHByaXZhdGUgUHJvdG8yTWFwRW51bUxpdGUoaW50IHZhbHVlKSB7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUpCiAgfQoKICAvKioKICAgKiBQcm90b2J1ZiBlbnVtIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGV9CiAgICovCiAgcHVibGljIGVudW0gUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUKICAgICAgaW1wbGVtZW50cyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sTWVzc2FnZUVudW0gewogICAgLyoqCiAgICAgKiA8Y29kZT5FX1BST1RPMl9NQVBfRU5VTV9GT09fTElURSA9IDA7PC9jb2RlPgogICAgICovCiAgICBFX1BST1RPMl9NQVBfRU5VTV9GT09fTElURSgwKSwKICAgIC8qKgogICAgICogPGNvZGU+RV9QUk9UTzJfTUFQX0VOVU1fQkFSX0xJVEUgPSAxOzwvY29kZT4KICAgICAqLwogICAgRV9QUk9UTzJfTUFQX0VOVU1fQkFSX0xJVEUoMSksCiAgICAvKioKICAgICAqIDxjb2RlPkVfUFJPVE8yX01BUF9FTlVNX0JBWl9MSVRFID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEVfUFJPVE8yX01BUF9FTlVNX0JBWl9MSVRFKDIpLAogICAgLyoqCiAgICAgKiA8Y29kZT5FX1BST1RPMl9NQVBfRU5VTV9FWFRSQV9MSVRFID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEVfUFJPVE8yX01BUF9FTlVNX0VYVFJBX0xJVEUoMyksCiAgICA7CgogICAgLyoqCiAgICAgKiA8Y29kZT5FX1BST1RPMl9NQVBfRU5VTV9GT09fTElURSA9IDA7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFX1BST1RPMl9NQVBfRU5VTV9GT09fTElURV9WQUxVRSA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPkVfUFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEVfUFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFX1ZBTFVFID0gMTsKICAgIC8qKgogICAgICogPGNvZGU+RV9QUk9UTzJfTUFQX0VOVU1fQkFaX0xJVEUgPSAyOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRV9QUk9UTzJfTUFQX0VOVU1fQkFaX0xJVEVfVkFMVUUgPSAyOwogICAgLyoqCiAgICAgKiA8Y29kZT5FX1BST1RPMl9NQVBfRU5VTV9FWFRSQV9MSVRFID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEVfUFJPVE8yX01BUF9FTlVNX0VYVFJBX0xJVEVfVkFMVUUgPSAzOwoKCiAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgc3RhdGljIFByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgIHJldHVybiBmb3JOdW1iZXIodmFsdWUpOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICBzd2l0Y2ggKHZhbHVlKSB7CiAgICAgICAgY2FzZSAwOiByZXR1cm4gRV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEU7CiAgICAgICAgY2FzZSAxOiByZXR1cm4gRV9QUk9UTzJfTUFQX0VOVU1fQkFSX0xJVEU7CiAgICAgICAgY2FzZSAyOiByZXR1cm4gRV9QUk9UTzJfTUFQX0VOVU1fQkFaX0xJVEU7CiAgICAgICAgY2FzZSAzOiByZXR1cm4gRV9QUk9UTzJfTUFQX0VOVU1fRVhUUkFfTElURTsKICAgICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxQcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgICAgICBpbnRlcm5hbEdldFZhbHVlTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxWYWx1ZU1hcDsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8CiAgICAgICAgUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+IGludGVybmFsVmFsdWVNYXAgPQogICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8UHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+KCkgewogICAgICAgICAgICBwdWJsaWMgUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZmluZFZhbHVlQnlOdW1iZXIoaW50IG51bWJlcikgewogICAgICAgICAgICAgIHJldHVybiBQcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZS5mb3JOdW1iZXIobnVtYmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKCiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yCiAgICAgICAgZ2V0VmFsdWVEZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpLmdldFZhbHVlcygpLmdldChvcmRpbmFsKCkpOwogICAgfQogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMSk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGVbXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICBwdWJsaWMgc3RhdGljIFByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIHZhbHVlT2YoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yIGRlc2MpIHsKICAgICAgaWYgKGRlc2MuZ2V0VHlwZSgpICE9IGdldERlc2NyaXB0b3IoKSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKAogICAgICAgICAgIkVudW1WYWx1ZURlc2NyaXB0b3IgaXMgbm90IGZvciB0aGlzIHR5cGUuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIFZBTFVFU1tkZXNjLmdldEluZGV4KCldOwogICAgfQoKICAgIHByaXZhdGUgZmluYWwgaW50IHZhbHVlOwoKICAgIHByaXZhdGUgUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUoaW50IHZhbHVlKSB7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUpCiAgfQoKICAvKioKICAgKiBQcm90b2J1ZiBlbnVtIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGV9CiAgICovCiAgcHVibGljIGVudW0gTWFwRW51bUxpdGUKICAgICAgaW1wbGVtZW50cyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sTWVzc2FnZUVudW0gewogICAgLyoqCiAgICAgKiA8Y29kZT5NQVBfRU5VTV9GT09fTElURSA9IDA7PC9jb2RlPgogICAgICovCiAgICBNQVBfRU5VTV9GT09fTElURSgwKSwKICAgIC8qKgogICAgICogPGNvZGU+TUFQX0VOVU1fQkFSX0xJVEUgPSAxOzwvY29kZT4KICAgICAqLwogICAgTUFQX0VOVU1fQkFSX0xJVEUoMSksCiAgICAvKioKICAgICAqIDxjb2RlPk1BUF9FTlVNX0JBWl9MSVRFID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIE1BUF9FTlVNX0JBWl9MSVRFKDIpLAogICAgOwoKICAgIC8qKgogICAgICogPGNvZGU+TUFQX0VOVU1fRk9PX0xJVEUgPSAwOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0VOVU1fRk9PX0xJVEVfVkFMVUUgPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5NQVBfRU5VTV9CQVJfTElURSA9IDE7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfRU5VTV9CQVJfTElURV9WQUxVRSA9IDE7CiAgICAvKioKICAgICAqIDxjb2RlPk1BUF9FTlVNX0JBWl9MSVRFID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9FTlVNX0JBWl9MSVRFX1ZBTFVFID0gMjsKCgogICAgcHVibGljIGZpbmFsIGludCBnZXROdW1iZXIoKSB7CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjZm9yTnVtYmVyKGludCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIHN0YXRpYyBNYXBFbnVtTGl0ZSB2YWx1ZU9mKGludCB2YWx1ZSkgewogICAgICByZXR1cm4gZm9yTnVtYmVyKHZhbHVlKTsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIE1hcEVudW1MaXRlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgIGNhc2UgMDogcmV0dXJuIE1BUF9FTlVNX0ZPT19MSVRFOwogICAgICAgIGNhc2UgMTogcmV0dXJuIE1BUF9FTlVNX0JBUl9MSVRFOwogICAgICAgIGNhc2UgMjogcmV0dXJuIE1BUF9FTlVNX0JBWl9MSVRFOwogICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPE1hcEVudW1MaXRlPgogICAgICAgIGludGVybmFsR2V0VmFsdWVNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbFZhbHVlTWFwOwogICAgfQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDwKICAgICAgICBNYXBFbnVtTGl0ZT4gaW50ZXJuYWxWYWx1ZU1hcCA9CiAgICAgICAgICBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxNYXBFbnVtTGl0ZT4oKSB7CiAgICAgICAgICAgIHB1YmxpYyBNYXBFbnVtTGl0ZSBmaW5kVmFsdWVCeU51bWJlcihpbnQgbnVtYmVyKSB7CiAgICAgICAgICAgICAgcmV0dXJuIE1hcEVudW1MaXRlLmZvck51bWJlcihudW1iZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IKICAgICAgICBnZXRWYWx1ZURlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCkuZ2V0VmFsdWVzKCkuZ2V0KG9yZGluYWwoKSk7CiAgICB9CiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuZ2V0RGVzY3JpcHRvcigpLmdldEVudW1UeXBlcygpLmdldCgyKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBNYXBFbnVtTGl0ZVtdIFZBTFVFUyA9IHZhbHVlcygpOwoKICAgIHB1YmxpYyBzdGF0aWMgTWFwRW51bUxpdGUgdmFsdWVPZigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IgZGVzYykgewogICAgICBpZiAoZGVzYy5nZXRUeXBlKCkgIT0gZ2V0RGVzY3JpcHRvcigpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAiRW51bVZhbHVlRGVzY3JpcHRvciBpcyBub3QgZm9yIHRoaXMgdHlwZS4iKTsKICAgICAgfQogICAgICByZXR1cm4gVkFMVUVTW2Rlc2MuZ2V0SW5kZXgoKV07CiAgICB9CgogICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CgogICAgcHJpdmF0ZSBNYXBFbnVtTGl0ZShpbnQgdmFsdWUpIHsKICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChlbnVtX3Njb3BlOnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSkKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdE1hcExpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RNYXBMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMkludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkludDMyKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBJbnQzMkludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcEludDMySW50MzJNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMkludDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJJbnQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDY0SW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDY0SW50NjQoCiAgICAgICAgbG9uZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQ2NEludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBJbnQ2NEludDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcEludDY0SW50NjRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwSW50NjRJbnQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcEludDY0SW50NjRPclRocm93KAogICAgICAgIGxvbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFVpbnQzMlVpbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFVpbnQzMlVpbnQzMigKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwVWludDMyVWludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBVaW50MzJVaW50MzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcFVpbnQzMlVpbnQzMk1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBVaW50MzJVaW50MzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFVpbnQ2NFVpbnQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFVpbnQ2NFVpbnQ2NCgKICAgICAgICBsb25nIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwVWludDY0VWludDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBVaW50NjRVaW50NjRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcFVpbnQ2NFVpbnQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBVaW50NjRVaW50NjRPclRocm93KAogICAgICAgIGxvbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNpbnQzMlNpbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFNpbnQzMlNpbnQzMigKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ludDMyU2ludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBTaW50MzJTaW50MzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcFNpbnQzMlNpbnQzMk1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTaW50MzJTaW50MzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ludDMyU2ludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNpbnQ2NFNpbnQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFNpbnQ2NFNpbnQ2NCgKICAgICAgICBsb25nIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwU2ludDY0U2ludDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBTaW50NjRTaW50NjRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcFNpbnQ2NFNpbnQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBTaW50NjRTaW50NjRPclRocm93KAogICAgICAgIGxvbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBGaXhlZDMyRml4ZWQzMigKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwRml4ZWQzMkZpeGVkMzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwRml4ZWQzMkZpeGVkMzJNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwRml4ZWQ2NEZpeGVkNjQoCiAgICAgICAgbG9uZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaXhlZDY0Rml4ZWQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwRml4ZWQ2NEZpeGVkNjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcEZpeGVkNjRGaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQzMlNmaXhlZDMyKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwU2ZpeGVkNjRTZml4ZWQ2NCgKICAgICAgICBsb25nIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJGbG9hdENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMyRmxvYXQoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRmxvYXRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+CiAgICBnZXRNYXBJbnQzMkZsb2F0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgZ2V0TWFwSW50MzJGbG9hdE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIGZsb2F0IGdldE1hcEludDMyRmxvYXRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBmbG9hdCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIGZsb2F0IGdldE1hcEludDMyRmxvYXRPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMkRvdWJsZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJEb3VibGUoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRG91YmxlTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgIGdldE1hcEludDMyRG91YmxlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPgogICAgZ2V0TWFwSW50MzJEb3VibGVNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIGRvdWJsZSBnZXRNYXBJbnQzMkRvdWJsZU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGRvdWJsZSBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgZG91YmxlIGdldE1hcEludDMyRG91YmxlT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwQm9vbEJvb2xDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEJvb2xCb29sKAogICAgICAgIGJvb2xlYW4ga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwQm9vbEJvb2xNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgIGdldE1hcEJvb2xCb29sKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgIGdldE1hcEJvb2xCb29sTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGdldE1hcEJvb2xCb29sT3JEZWZhdWx0KAogICAgICAgIGJvb2xlYW4ga2V5LAogICAgICAgIGJvb2xlYW4gZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gZ2V0TWFwQm9vbEJvb2xPclRocm93KAogICAgICAgIGJvb2xlYW4ga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTdHJpbmdTdHJpbmdDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwU3RyaW5nU3RyaW5nKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgZ2V0TWFwU3RyaW5nU3RyaW5nKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgIGdldE1hcFN0cmluZ1N0cmluZ01hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yRGVmYXVsdCgKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0TWFwU3RyaW5nU3RyaW5nT3JUaHJvdygKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMkJ5dGVzQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJCeXRlcygKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJCeXRlc01hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgIGdldE1hcEludDMyQnl0ZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICBnZXRNYXBJbnQzMkJ5dGVzTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE1hcEludDMyQnl0ZXNPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0TWFwSW50MzJCeXRlc09yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJFbnVtQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMyRW51bSgKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJFbnVtTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZT4KICAgIGdldE1hcEludDMyRW51bSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgZ2V0TWFwSW50MzJFbnVtTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSAgICAgICAgIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgKi8KICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMyRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+CiAgICBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4KICAgIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgdGVib3JpbmcgPSAxODs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRUZWJvcmluZ0NvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zVGVib3JpbmcoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldFRlYm9yaW5nTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRUZWJvcmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRUZWJvcmluZ01hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFRlYm9yaW5nT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0VGVib3JpbmdPclRocm93KAogICAgICAgIGludCBrZXkpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdE1hcExpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0TWFwTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdE1hcExpdGUpCiAgICAgIFRlc3RNYXBMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0TWFwTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0TWFwTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RNYXBMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RNYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgaW50IG51bWJlcikgewogICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKTsKICAgICAgICBjYXNlIDI6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCk7CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCk7CiAgICAgICAgY2FzZSA0OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCk7CiAgICAgICAgY2FzZSA1OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCk7CiAgICAgICAgY2FzZSA2OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCk7CiAgICAgICAgY2FzZSA3OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKTsKICAgICAgICBjYXNlIDg6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpOwogICAgICAgIGNhc2UgOToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKTsKICAgICAgICBjYXNlIDEwOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpOwogICAgICAgIGNhc2UgMTE6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCk7CiAgICAgICAgY2FzZSAxMjoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCk7CiAgICAgICAgY2FzZSAxMzoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCk7CiAgICAgICAgY2FzZSAxNDoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpOwogICAgICAgIGNhc2UgMTU6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCk7CiAgICAgICAgY2FzZSAxNjoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpOwogICAgICAgIGNhc2UgMTc6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCk7CiAgICAgICAgY2FzZSAxODoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldFRlYm9yaW5nKCk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICB9CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlLmNsYXNzLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9JTlQzMl9GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDApOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBJbnQzMkludDMyXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKSB7CiAgICAgIGlmIChtYXBJbnQzMkludDMyXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkludDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkludDMyKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBJbnQzMkludDMyKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJJbnQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBJbnQzMkludDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDY0X0lOVDY0X0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwSW50NjRJbnQ2NF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkgewogICAgICBpZiAobWFwSW50NjRJbnQ2NF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50NjRJbnQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDY0SW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50NjRJbnQ2NCgKICAgICAgICBsb25nIGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDY0SW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEludDY0SW50NjQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQ2NEludDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEludDY0SW50NjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEludDY0SW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEludDY0SW50NjRPclRocm93KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9VSU5UMzJfVUlOVDMyX0ZJRUxEX05VTUJFUiA9IDM7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuVUlOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlVJTlQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFVpbnQzMlVpbnQzMl87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKSB7CiAgICAgIGlmIChtYXBVaW50MzJVaW50MzJfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwVWludDMyVWludDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFVpbnQzMlVpbnQzMigKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBVaW50MzJVaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgcmV0dXJuIGdldE1hcFVpbnQzMlVpbnQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwVWludDMyVWludDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQzMlVpbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX1VJTlQ2NF9VSU5UNjRfRklFTERfTlVNQkVSID0gNDsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcFVpbnQ2NFVpbnQ2NERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBVaW50NjRVaW50NjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5VSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlVJTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBVaW50NjRVaW50NjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkgewogICAgICBpZiAobWFwVWludDY0VWludDY0XyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFVpbnQ2NFVpbnQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQ2NFVpbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBVaW50NjRVaW50NjQoCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwVWludDY0VWludDY0KCkgewogICAgICByZXR1cm4gZ2V0TWFwVWludDY0VWludDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBVaW50NjRVaW50NjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcFVpbnQ2NFVpbnQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwVWludDY0VWludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TSU5UMzJfU0lOVDMyX0ZJRUxEX05VTUJFUiA9IDU7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0lOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNJTlQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFNpbnQzMlNpbnQzMl87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgIGlmIChtYXBTaW50MzJTaW50MzJfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwU2ludDMyU2ludDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNpbnQzMlNpbnQzMigKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTaW50MzJTaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNpbnQzMlNpbnQzMigpIHsKICAgICAgcmV0dXJuIGdldE1hcFNpbnQzMlNpbnQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwU2ludDMyU2ludDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX1NJTlQ2NF9TSU5UNjRfRklFTERfTlVNQkVSID0gNjsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcFNpbnQ2NFNpbnQ2NERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTaW50NjRTaW50NjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNJTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBTaW50NjRTaW50NjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkgewogICAgICBpZiAobWFwU2ludDY0U2ludDY0XyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU2ludDY0U2ludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFNpbnQ2NFNpbnQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQ2NFNpbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTaW50NjRTaW50NjQoCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ludDY0U2ludDY0KCkgewogICAgICByZXR1cm4gZ2V0TWFwU2ludDY0U2ludDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTaW50NjRTaW50NjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcFNpbnQ2NFNpbnQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9GSVhFRDMyX0ZJWEVEMzJfRklFTERfTlVNQkVSID0gNzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkMzJGaXhlZDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRklYRUQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDMyLAogICAgICAgICAgICAgICAgICAwKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwRml4ZWQzMkZpeGVkMzJfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgIGlmIChtYXBGaXhlZDMyRml4ZWQzMl8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEZpeGVkMzJGaXhlZDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgIHJldHVybiBnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0ZJWEVENjRfRklYRUQ2NF9GSUVMRF9OVU1CRVIgPSA4OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcEZpeGVkNjRGaXhlZDY0XzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkgewogICAgICBpZiAobWFwRml4ZWQ2NEZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBGaXhlZDY0Rml4ZWQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkNjRGaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEZpeGVkNjRGaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TRklYRUQzMl9TRklYRUQzMl9GSUVMRF9OVU1CRVIgPSA5OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0ZJWEVEMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0ZJWEVEMzIsCiAgICAgICAgICAgICAgICAgIDApOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBTZml4ZWQzMlNmaXhlZDMyXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgIGlmIChtYXBTZml4ZWQzMlNmaXhlZDMyXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBTZml4ZWQzMlNmaXhlZDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMkNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQzMlNmaXhlZDMyKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkgewogICAgICByZXR1cm4gZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX1NGSVhFRDY0X1NGSVhFRDY0X0ZJRUxEX05VTUJFUiA9IDEwOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU2ZpeGVkNjRTZml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0ZJWEVENjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNGSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgaWYgKG1hcFNmaXhlZDY0U2ZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQ2NFNmaXhlZDY0KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0ZMT0FUX0ZJRUxEX05VTUJFUiA9IDExOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0Pm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GTE9BVCwKICAgICAgICAgICAgICAgICAgMEYpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwSW50MzJGbG9hdF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpIHsKICAgICAgaWYgKG1hcEludDMyRmxvYXRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkZsb2F0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRmxvYXRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMkZsb2F0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZsb2F0KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZsb2F0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZ2V0TWFwSW50MzJGbG9hdCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEludDMyRmxvYXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBnZXRNYXBJbnQzMkZsb2F0TWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZsb2F0IGdldE1hcEludDMyRmxvYXRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBmbG9hdCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZsb2F0IGdldE1hcEludDMyRmxvYXRPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9ET1VCTEVfRklFTERfTlVNQkVSID0gMTI7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJEb3VibGVFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5ET1VCTEUsCiAgICAgICAgICAgICAgICAgIDBEKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXBJbnQzMkRvdWJsZV87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkgewogICAgICBpZiAobWFwSW50MzJEb3VibGVfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkRvdWJsZV87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDMyRG91YmxlQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkRvdWJsZSgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRG91YmxlTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGdldE1hcEludDMyRG91YmxlKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJEb3VibGVNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBnZXRNYXBJbnQzMkRvdWJsZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBkb3VibGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZG91YmxlIGdldE1hcEludDMyRG91YmxlT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9CT09MX0JPT0xfRklFTERfTlVNQkVSID0gMTM7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkJPT0wsCiAgICAgICAgICAgICAgICAgIGZhbHNlLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkJPT0wsCiAgICAgICAgICAgICAgICAgIGZhbHNlKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gbWFwQm9vbEJvb2xfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKSB7CiAgICAgIGlmIChtYXBCb29sQm9vbF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEJvb2xCb29sXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwQm9vbEJvb2xDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEJvb2xCb29sKAogICAgICAgIGJvb2xlYW4ga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEJvb2xCb29sTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBnZXRNYXBCb29sQm9vbCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEJvb2xCb29sTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGdldE1hcEJvb2xCb29sTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZ2V0TWFwQm9vbEJvb2xPckRlZmF1bHQoCiAgICAgICAgYm9vbGVhbiBrZXksCiAgICAgICAgYm9vbGVhbiBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBnZXRNYXBCb29sQm9vbE9yVGhyb3coCiAgICAgICAgYm9vbGVhbiBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TVFJJTkdfU1RSSU5HX0ZJRUxEX05VTUJFUiA9IDE0OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU1RSSU5HLAogICAgICAgICAgICAgICAgICAiIiwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TVFJJTkcsCiAgICAgICAgICAgICAgICAgICIiKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcFN0cmluZ1N0cmluZ187CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkgewogICAgICBpZiAobWFwU3RyaW5nU3RyaW5nXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFN0cmluZ1N0cmluZ187CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFN0cmluZ1N0cmluZ0NvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU3RyaW5nU3RyaW5nKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBnZXRNYXBTdHJpbmdTdHJpbmcoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZ2V0TWFwU3RyaW5nU3RyaW5nT3JEZWZhdWx0KAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZGVmYXVsdFZhbHVlKSB7CiAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yVGhyb3coCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0JZVEVTX0ZJRUxEX05VTUJFUiA9IDE1OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5CWVRFUywKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG1hcEludDMyQnl0ZXNfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKSB7CiAgICAgIGlmIChtYXBJbnQzMkJ5dGVzXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkJ5dGVzXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJCeXRlc0NvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJCeXRlcygKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJCeXRlc01hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IGdldE1hcEludDMyQnl0ZXMoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQzMkJ5dGVzTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZ2V0TWFwSW50MzJCeXRlc01hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0TWFwSW50MzJCeXRlc09yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfSU5UMzJfRU5VTV9GSUVMRF9OVU1CRVIgPSAxNjsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyRW51bURlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkVudW1FbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5FTlVNLAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlLk1BUF9FTlVNX0ZPT19MSVRFLmdldE51bWJlcigpKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwSW50MzJFbnVtXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpIHsKICAgICAgaWYgKG1hcEludDMyRW51bV8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDMyRW51bURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkVudW1fOwogICAgfQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5Db252ZXJ0ZXI8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+IG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyID0KICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyLm5ld0VudW1Db252ZXJ0ZXIoCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlLmludGVybmFsR2V0VmFsdWVNYXAoKSwKICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUuTUFQX0VOVU1fRk9PX0xJVEUpOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZT4KICAgIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwKSB7CiAgICAgIHJldHVybiBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUsIGphdmEubGFuZy5JbnRlZ2VyPigKICAgICAgICAgICAgICBtYXAsIG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyKTsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJFbnVtQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkVudW0oCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJFbnVtTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBnZXRNYXBJbnQzMkVudW0oKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQzMkVudW1NYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBnZXRNYXBJbnQzMkVudW1NYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRNYXBJbnQzMkVudW1NYXAoCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpKTt9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGdldE1hcEludDMyRW51bU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgPyBtYXBJbnQzMkVudW1WYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKQogICAgICAgICAgICAgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGdldE1hcEludDMyRW51bU9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0ZPUkVJR05fTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAxNzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuTUVTU0FHRSwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+CiAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgIGlmIChtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJGb3JlaWduTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZUNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgVEVCT1JJTkdfRklFTERfTlVNQkVSID0gMTg7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBUZWJvcmluZ0RlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9UZWJvcmluZ0VudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdGVib3JpbmdfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0VGVib3JpbmcoKSB7CiAgICAgIGlmICh0ZWJvcmluZ18gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIFRlYm9yaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRlYm9yaW5nXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0VGVib3JpbmdDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0VGVib3JpbmcoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc1RlYm9yaW5nKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0VGVib3JpbmdNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldFRlYm9yaW5nKCkgewogICAgICByZXR1cm4gZ2V0VGVib3JpbmdNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgdGVib3JpbmcgPSAxODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0VGVib3JpbmdNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFRlYm9yaW5nT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgdGVib3JpbmcgPSAxODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0VGVib3JpbmdPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCksCiAgICAgICAgICBNYXBJbnQzMkludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKSwKICAgICAgICAgIE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMik7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCksCiAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMyk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUxvbmdNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCksCiAgICAgICAgICBNYXBVaW50NjRVaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgNCk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCksCiAgICAgICAgICBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgNSk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUxvbmdNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCksCiAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgNik7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSwKICAgICAgICAgIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDcpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCksCiAgICAgICAgICBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICA4KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCksCiAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDkpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKSwKICAgICAgICAgIE1hcFNmaXhlZDY0U2ZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTApOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKSwKICAgICAgICAgIE1hcEludDMyRmxvYXREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTEpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCksCiAgICAgICAgICBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxMik7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUJvb2xlYW5NYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKSwKICAgICAgICAgIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEzKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplU3RyaW5nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLAogICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDE0KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCksCiAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDE1KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKSwKICAgICAgICAgIE1hcEludDMyRW51bURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxNik7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLAogICAgICAgICAgTWFwSW50MzJGb3JlaWduTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxNyk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0VGVib3JpbmcoKSwKICAgICAgICAgIFRlYm9yaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDE4KTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgbWFwSW50MzJJbnQzMl9fID0gTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMSwgbWFwSW50MzJJbnQzMl9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgIG1hcEludDY0SW50NjRfXyA9IE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDIsIG1hcEludDY0SW50NjRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcFVpbnQzMlVpbnQzMl9fID0gTWFwVWludDMyVWludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgzLCBtYXBVaW50MzJVaW50MzJfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgIG1hcFVpbnQ2NFVpbnQ2NF9fID0gTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg0LCBtYXBVaW50NjRVaW50NjRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcFNpbnQzMlNpbnQzMl9fID0gTWFwU2ludDMyU2ludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg1LCBtYXBTaW50MzJTaW50MzJfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgIG1hcFNpbnQ2NFNpbnQ2NF9fID0gTWFwU2ludDY0U2ludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg2LCBtYXBTaW50NjRTaW50NjRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgbWFwRml4ZWQzMkZpeGVkMzJfXyA9IE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg3LCBtYXBGaXhlZDMyRml4ZWQzMl9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBGaXhlZDY0Rml4ZWQ2NF9fID0gTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDgsIG1hcEZpeGVkNjRGaXhlZDY0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgbWFwU2ZpeGVkMzJTZml4ZWQzMl9fID0gTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoOSwgbWFwU2ZpeGVkMzJTZml4ZWQzMl9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgIG1hcFNmaXhlZDY0U2ZpeGVkNjRfXyA9IE1hcFNmaXhlZDY0U2ZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEwLCBtYXBTZml4ZWQ2NFNmaXhlZDY0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgICAgICBtYXBJbnQzMkZsb2F0X18gPSBNYXBJbnQzMkZsb2F0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMSwgbWFwSW50MzJGbG9hdF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgbWFwSW50MzJEb3VibGVfXyA9IE1hcEludDMyRG91YmxlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMiwgbWFwSW50MzJEb3VibGVfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICAgICAgbWFwQm9vbEJvb2xfXyA9IE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMywgbWFwQm9vbEJvb2xfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICAgICAgbWFwU3RyaW5nU3RyaW5nX18gPSBNYXBTdHJpbmdTdHJpbmdEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE0LCBtYXBTdHJpbmdTdHJpbmdfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgICAgIG1hcEludDMyQnl0ZXNfXyA9IE1hcEludDMyQnl0ZXNEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE1LCBtYXBJbnQzMkJ5dGVzX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBtYXBJbnQzMkVudW1fXyA9IE1hcEludDMyRW51bURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTYsIG1hcEludDMyRW51bV9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+CiAgICAgICAgbWFwSW50MzJGb3JlaWduTWVzc2FnZV9fID0gTWFwSW50MzJGb3JlaWduTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTcsIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0VGVib3JpbmcoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgdGVib3JpbmdfXyA9IFRlYm9yaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxOCwgdGVib3JpbmdfXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBvdGhlciA9IChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlKSBvYmo7CgogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJJbnQzMigpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJFbnVtKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRUZWJvcmluZygpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0VGVib3JpbmcoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQzMl9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQ2NF9JTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1VJTlQzMl9VSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1VJTlQ2NF9VSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1NJTlQzMl9TSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1NJTlQ2NF9TSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfRklYRUQzMl9GSVhFRDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfRklYRUQ2NF9GSVhFRDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9TRklYRUQzMl9TRklYRUQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9TRklYRUQ2NF9TRklYRUQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQzMl9GTE9BVF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UMzJfRE9VQkxFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfQk9PTF9CT09MX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1NUUklOR19TVFJJTkdfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQzMl9CWVRFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQzMl9GT1JFSUdOX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgVEVCT1JJTkdfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0VGVib3JpbmcoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RNYXBMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RNYXBMaXRlKQogICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpOwogICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCk7CiAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpOwogICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKTsKICAgICAgICAgIGNhc2UgNToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCk7CiAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpOwogICAgICAgICAgY2FzZSA3OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpOwogICAgICAgICAgY2FzZSA4OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpOwogICAgICAgICAgY2FzZSA5OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCk7CiAgICAgICAgICBjYXNlIDEwOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCk7CiAgICAgICAgICBjYXNlIDExOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCk7CiAgICAgICAgICBjYXNlIDEyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpOwogICAgICAgICAgY2FzZSAxMzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKTsKICAgICAgICAgIGNhc2UgMTQ6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpOwogICAgICAgICAgY2FzZSAxNToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpOwogICAgICAgICAgY2FzZSAxNjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCk7CiAgICAgICAgICBjYXNlIDE3OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCk7CiAgICAgICAgICBjYXNlIDE4OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRUZWJvcmluZygpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKTsKICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKTsKICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpOwogICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCk7CiAgICAgICAgICBjYXNlIDU6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKTsKICAgICAgICAgIGNhc2UgNjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpOwogICAgICAgICAgY2FzZSA3OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKTsKICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAgICAgICBjYXNlIDk6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCk7CiAgICAgICAgICBjYXNlIDEwOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpOwogICAgICAgICAgY2FzZSAxMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKTsKICAgICAgICAgIGNhc2UgMTI6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpOwogICAgICAgICAgY2FzZSAxMzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCk7CiAgICAgICAgICBjYXNlIDE0OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCk7CiAgICAgICAgICBjYXNlIDE1OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpOwogICAgICAgICAgY2FzZSAxNjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpOwogICAgICAgICAgY2FzZSAxNzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKTsKICAgICAgICAgIGNhc2UgMTg6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVUZWJvcmluZygpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUuY2xhc3MsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIGJ1aWxkKCkgewogICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHJlc3VsdCA9IG5ldyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkludDMyXyA9IGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMySW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQ2NEludDY0XyA9IGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDY0SW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50MzJVaW50MzJfID0gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKTsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50MzJVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50NjRVaW50NjRfID0gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50NjRVaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50MzJTaW50MzJfID0gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50MzJTaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50NjRTaW50NjRfID0gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50NjRTaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBGaXhlZDMyRml4ZWQzMl8gPSBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgICByZXN1bHQubWFwRml4ZWQzMkZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA4MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBGaXhlZDY0Rml4ZWQ2NF8gPSBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAgICAgICByZXN1bHQubWFwRml4ZWQ2NEZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTZml4ZWQzMlNmaXhlZDMyXyA9IGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgICAgICAgcmVzdWx0Lm1hcFNmaXhlZDMyU2ZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTZml4ZWQ2NFNmaXhlZDY0XyA9IGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpOwogICAgICAgICAgcmVzdWx0Lm1hcFNmaXhlZDY0U2ZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDQwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkZsb2F0XyA9IGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMyRmxvYXRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDgwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkRvdWJsZV8gPSBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCk7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJEb3VibGVfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBCb29sQm9vbF8gPSBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCk7CiAgICAgICAgICByZXN1bHQubWFwQm9vbEJvb2xfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTdHJpbmdTdHJpbmdfID0gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTdHJpbmdTdHJpbmdfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwNDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkJ5dGVzXyA9IGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMyQnl0ZXNfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwODAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkVudW1fID0gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKTsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkVudW1fLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAxMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkZvcmVpZ25NZXNzYWdlXyA9IGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmJ1aWxkKE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAyMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC50ZWJvcmluZ18gPSBpbnRlcm5hbEdldFRlYm9yaW5nKCk7CiAgICAgICAgICByZXN1bHQudGVib3JpbmdfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDY0SW50NjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEJvb2xCb29sKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMTAwMDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0VGVib3JpbmcoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDIwMDAwOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwSW50MzJJbnQzMl9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkludDMyX18uZ2V0S2V5KCksIG1hcEludDMySW50MzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMAogICAgICAgICAgICAgIGNhc2UgMTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwSW50NjRJbnQ2NF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50NjRJbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQ2NEludDY0X18uZ2V0S2V5KCksIG1hcEludDY0SW50NjRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxOAogICAgICAgICAgICAgIGNhc2UgMjY6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwVWludDMyVWludDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBVaW50MzJVaW50MzJfXy5nZXRLZXkoKSwgbWFwVWludDMyVWludDMyX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjYKICAgICAgICAgICAgICBjYXNlIDM0OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgICAgICAgIG1hcFVpbnQ2NFVpbnQ2NF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwVWludDY0VWludDY0X18uZ2V0S2V5KCksIG1hcFVpbnQ2NFVpbnQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM0CiAgICAgICAgICAgICAgY2FzZSA0MjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBtYXBTaW50MzJTaW50MzJfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcFNpbnQzMlNpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNpbnQzMlNpbnQzMl9fLmdldEtleSgpLCBtYXBTaW50MzJTaW50MzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0MgogICAgICAgICAgICAgIGNhc2UgNTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwU2ludDY0U2ludDY0X18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBTaW50NjRTaW50NjRfXy5nZXRLZXkoKSwgbWFwU2ludDY0U2ludDY0X18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTAKICAgICAgICAgICAgICBjYXNlIDU4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIG1hcEZpeGVkMzJGaXhlZDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwRml4ZWQzMkZpeGVkMzJfXy5nZXRLZXkoKSwgbWFwRml4ZWQzMkZpeGVkMzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1OAogICAgICAgICAgICAgIGNhc2UgNjY6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwRml4ZWQ2NEZpeGVkNjRfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcEZpeGVkNjRGaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBGaXhlZDY0Rml4ZWQ2NF9fLmdldEtleSgpLCBtYXBGaXhlZDY0Rml4ZWQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDY2CiAgICAgICAgICAgICAgY2FzZSA3NDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBtYXBTZml4ZWQzMlNmaXhlZDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNmaXhlZDMyU2ZpeGVkMzJfXy5nZXRLZXkoKSwgbWFwU2ZpeGVkMzJTZml4ZWQzMl9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc0CiAgICAgICAgICAgICAgY2FzZSA4MjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICAgICAgICBtYXBTZml4ZWQ2NFNmaXhlZDY0X18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNmaXhlZDY0U2ZpeGVkNjRfXy5nZXRLZXkoKSwgbWFwU2ZpeGVkNjRTZml4ZWQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgyCiAgICAgICAgICAgICAgY2FzZSA5MDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgICAgICAgICAgICAgbWFwSW50MzJGbG9hdF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkZsb2F0X18uZ2V0S2V5KCksIG1hcEludDMyRmxvYXRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA5MAogICAgICAgICAgICAgIGNhc2UgOTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgICAgICAgICBtYXBJbnQzMkRvdWJsZV9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEludDMyRG91YmxlX18uZ2V0S2V5KCksIG1hcEludDMyRG91YmxlX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTgKICAgICAgICAgICAgICBjYXNlIDEwNjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICAgICAgICAgICAgICBtYXBCb29sQm9vbF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwQm9vbEJvb2xEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEJvb2xCb29sX18uZ2V0S2V5KCksIG1hcEJvb2xCb29sX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTA2CiAgICAgICAgICAgICAgY2FzZSAxMTQ6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgICAgICAgICAgICAgIG1hcFN0cmluZ1N0cmluZ19fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwU3RyaW5nU3RyaW5nX18uZ2V0S2V5KCksIG1hcFN0cmluZ1N0cmluZ19fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDExNAogICAgICAgICAgICAgIGNhc2UgMTIyOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICAgICAgICAgICAgICBtYXBJbnQzMkJ5dGVzX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEludDMyQnl0ZXNfXy5nZXRLZXkoKSwgbWFwSW50MzJCeXRlc19fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEyMgogICAgICAgICAgICAgIGNhc2UgMTMwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnl0ZXMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwSW50MzJFbnVtX18gPSBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKS5wYXJzZUZyb20oYnl0ZXMpOwogICAgICAgICAgICAgICAgaWYgKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUuZm9yTnVtYmVyKG1hcEludDMyRW51bV9fLmdldFZhbHVlKCkpID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duTGVuZ3RoRGVsaW1pdGVkRmllbGQoMTYsIGJ5dGVzKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkVudW1fXy5nZXRLZXkoKSwgbWFwSW50MzJFbnVtX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMzAKICAgICAgICAgICAgICBjYXNlIDEzODogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPgogICAgICAgICAgICAgICAgbWFwSW50MzJGb3JlaWduTWVzc2FnZV9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJGb3JlaWduTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlX18uZ2V0S2V5KCksIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMzgKICAgICAgICAgICAgICBjYXNlIDE0NjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICB0ZWJvcmluZ19fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgVGVib3JpbmdEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIHRlYm9yaW5nX18uZ2V0S2V5KCksIHRlYm9yaW5nX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTQ2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwSW50MzJJbnQzMl87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKSB7CiAgICAgICAgaWYgKG1hcEludDMySW50MzJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJJbnQzMl87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKSB7CiAgICAgICAgaWYgKG1hcEludDMySW50MzJfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMySW50MzJfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwSW50MzJJbnQzMl8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEludDMySW50MzJfID0gbWFwSW50MzJJbnQzMl8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDMySW50MzJfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJJbnQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMySW50MzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcEludDMySW50MzIoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEludDMySW50MzJNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwSW50MzJJbnQzMk1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkludDMyT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQzMkludDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEludDMySW50MzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkludDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBJbnQzMkludDMyKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQzMkludDMyKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBJbnQ2NEludDY0XzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpIHsKICAgICAgICBpZiAobWFwSW50NjRJbnQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQ2NEludDY0XzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpIHsKICAgICAgICBpZiAobWFwSW50NjRJbnQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgbWFwSW50NjRJbnQ2NF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBJbnQ2NEludDY0Xy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwSW50NjRJbnQ2NF8gPSBtYXBJbnQ2NEludDY0Xy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwSW50NjRJbnQ2NF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQ2NEludDY0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50NjRJbnQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQ2NEludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEludDY0SW50NjQoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEludDY0SW50NjRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwSW50NjRJbnQ2NE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBJbnQ2NEludDY0T3JEZWZhdWx0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwSW50NjRJbnQ2NE9yVGhyb3coCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEludDY0SW50NjQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50NjRJbnQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQ2NEludDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBJbnQ2NEludDY0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEludDY0SW50NjQoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFVpbnQzMlVpbnQzMl87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgICBpZiAobWFwVWludDMyVWludDMyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFVpbnQzMlVpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwVWludDMyVWludDMyXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkgewogICAgICAgIGlmIChtYXBVaW50MzJVaW50MzJfID09IG51bGwpIHsKICAgICAgICAgIG1hcFVpbnQzMlVpbnQzMl8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFVpbnQzMlVpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcFVpbnQzMlVpbnQzMl8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcFVpbnQzMlVpbnQzMl8gPSBtYXBVaW50MzJVaW50MzJfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBVaW50MzJVaW50MzJfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwVWludDMyVWludDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBVaW50MzJVaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwVWludDMyVWludDMyKCkgewogICAgICAgIHJldHVybiBnZXRNYXBVaW50MzJVaW50MzJNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFVpbnQzMlVpbnQzMk1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQzMlVpbnQzMk9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQzMlVpbnQzMk9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBVaW50MzJVaW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwVWludDMyVWludDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcFVpbnQzMlVpbnQzMigKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwVWludDMyVWludDMyKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcFVpbnQ2NFVpbnQ2NF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpIHsKICAgICAgICBpZiAobWFwVWludDY0VWludDY0XyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFVpbnQ2NFVpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwVWludDY0VWludDY0XzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkgewogICAgICAgIGlmIChtYXBVaW50NjRVaW50NjRfID09IG51bGwpIHsKICAgICAgICAgIG1hcFVpbnQ2NFVpbnQ2NF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFVpbnQ2NFVpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcFVpbnQ2NFVpbnQ2NF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcFVpbnQ2NFVpbnQ2NF8gPSBtYXBVaW50NjRVaW50NjRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBVaW50NjRVaW50NjRfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDY0VWludDY0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwVWludDY0VWludDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwVWludDY0VWludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFVpbnQ2NFVpbnQ2NCgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwVWludDY0VWludDY0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBVaW50NjRVaW50NjRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwVWludDY0VWludDY0T3JEZWZhdWx0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwVWludDY0VWludDY0T3JUaHJvdygKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBVaW50NjRVaW50NjQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDgpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwVWludDY0VWludDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBVaW50NjRVaW50NjQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwVWludDY0VWludDY0KAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFNpbnQzMlNpbnQzMl87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpIHsKICAgICAgICBpZiAobWFwU2ludDMyU2ludDMyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFNpbnQzMlNpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwU2ludDMyU2ludDMyXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkgewogICAgICAgIGlmIChtYXBTaW50MzJTaW50MzJfID09IG51bGwpIHsKICAgICAgICAgIG1hcFNpbnQzMlNpbnQzMl8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFNpbnQzMlNpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcFNpbnQzMlNpbnQzMl8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcFNpbnQzMlNpbnQzMl8gPSBtYXBTaW50MzJTaW50MzJfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBTaW50MzJTaW50MzJfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU2ludDMyU2ludDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTaW50MzJTaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwU2ludDMyU2ludDMyKCkgewogICAgICAgIHJldHVybiBnZXRNYXBTaW50MzJTaW50MzJNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNpbnQzMlNpbnQzMk1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwU2ludDMyU2ludDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcFNpbnQzMlNpbnQzMigKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwU2ludDMyU2ludDMyKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcFNpbnQ2NFNpbnQ2NF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpIHsKICAgICAgICBpZiAobWFwU2ludDY0U2ludDY0XyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFNpbnQ2NFNpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwU2ludDY0U2ludDY0XzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkgewogICAgICAgIGlmIChtYXBTaW50NjRTaW50NjRfID09IG51bGwpIHsKICAgICAgICAgIG1hcFNpbnQ2NFNpbnQ2NF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFNpbnQ2NFNpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcFNpbnQ2NFNpbnQ2NF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcFNpbnQ2NFNpbnQ2NF8gPSBtYXBTaW50NjRTaW50NjRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBTaW50NjRTaW50NjRfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDY0U2ludDY0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU2ludDY0U2ludDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ludDY0U2ludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNpbnQ2NFNpbnQ2NCgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwU2ludDY0U2ludDY0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTaW50NjRTaW50NjRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JEZWZhdWx0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JUaHJvdygKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMjApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwU2ludDY0U2ludDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBTaW50NjRTaW50NjQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwU2ludDY0U2ludDY0KAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcEZpeGVkMzJGaXhlZDMyXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgICAgaWYgKG1hcEZpeGVkMzJGaXhlZDMyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBGaXhlZDMyRml4ZWQzMl87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkgewogICAgICAgIGlmIChtYXBGaXhlZDMyRml4ZWQzMl8gPT0gbnVsbCkgewogICAgICAgICAgbWFwRml4ZWQzMkZpeGVkMzJfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEZpeGVkMzJGaXhlZDMyXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwRml4ZWQzMkZpeGVkMzJfID0gbWFwRml4ZWQzMkZpeGVkMzJfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBGaXhlZDMyRml4ZWQzMl87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEZpeGVkMzJGaXhlZDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcEZpeGVkMzJGaXhlZDMyKCkgewogICAgICAgIHJldHVybiBnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEZpeGVkMzJGaXhlZDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDQwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEZpeGVkMzJGaXhlZDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBGaXhlZDMyRml4ZWQzMigKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBGaXhlZDY0Rml4ZWQ2NF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkgewogICAgICAgIGlmIChtYXBGaXhlZDY0Rml4ZWQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwRml4ZWQ2NEZpeGVkNjRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgICBpZiAobWFwRml4ZWQ2NEZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICAgIG1hcEZpeGVkNjRGaXhlZDY0XyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBGaXhlZDY0Rml4ZWQ2NF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEZpeGVkNjRGaXhlZDY0XyA9IG1hcEZpeGVkNjRGaXhlZDY0Xy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwRml4ZWQ2NEZpeGVkNjRfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBGaXhlZDY0Rml4ZWQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwRml4ZWQ2NEZpeGVkNjQoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRPckRlZmF1bHQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yVGhyb3coCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA4MCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBGaXhlZDY0Rml4ZWQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwU2ZpeGVkMzJTZml4ZWQzMl87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgICAgaWYgKG1hcFNmaXhlZDMyU2ZpeGVkMzJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwU2ZpeGVkMzJTZml4ZWQzMl87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgICAgaWYgKG1hcFNmaXhlZDMyU2ZpeGVkMzJfID09IG51bGwpIHsKICAgICAgICAgIG1hcFNmaXhlZDMyU2ZpeGVkMzJfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwU2ZpeGVkMzJTZml4ZWQzMl8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcFNmaXhlZDMyU2ZpeGVkMzJfID0gbWFwU2ZpeGVkMzJTZml4ZWQzMl8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcFNmaXhlZDMyU2ZpeGVkMzJfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNmaXhlZDMyU2ZpeGVkMzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBTZml4ZWQzMlNmaXhlZDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMTAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcFNmaXhlZDMyU2ZpeGVkMzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBTZml4ZWQzMlNmaXhlZDMyKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBTZml4ZWQzMlNmaXhlZDMyKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBTZml4ZWQ2NFNmaXhlZDY0XzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgICBpZiAobWFwU2ZpeGVkNjRTZml4ZWQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBTZml4ZWQ2NFNmaXhlZDY0XzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgICBpZiAobWFwU2ZpeGVkNjRTZml4ZWQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgbWFwU2ZpeGVkNjRTZml4ZWQ2NF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFNmaXhlZDY0U2ZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBTZml4ZWQ2NFNmaXhlZDY0Xy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwU2ZpeGVkNjRTZml4ZWQ2NF8gPSBtYXBTZml4ZWQ2NFNmaXhlZDY0Xy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwU2ZpeGVkNjRTZml4ZWQ2NF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNmaXhlZDY0U2ZpeGVkNjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkgewogICAgICAgIHJldHVybiBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0T3JEZWZhdWx0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRPclRocm93KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBTZml4ZWQ2NFNmaXhlZDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMjAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBTZml4ZWQ2NFNmaXhlZDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBTZml4ZWQ2NFNmaXhlZDY0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBTZml4ZWQ2NFNmaXhlZDY0KAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwSW50MzJGbG9hdF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkgewogICAgICAgIGlmIChtYXBJbnQzMkZsb2F0XyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMyRmxvYXREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyRmxvYXRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpIHsKICAgICAgICBpZiAobWFwSW50MzJGbG9hdF8gPT0gbnVsbCkgewogICAgICAgICAgbWFwSW50MzJGbG9hdF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMyRmxvYXREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBJbnQzMkZsb2F0Xy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwSW50MzJGbG9hdF8gPSBtYXBJbnQzMkZsb2F0Xy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwSW50MzJGbG9hdF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkZsb2F0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRmxvYXQoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZsb2F0TWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBnZXRNYXBJbnQzMkZsb2F0KCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQzMkZsb2F0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZ2V0TWFwSW50MzJGbG9hdE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZsb2F0IGdldE1hcEludDMyRmxvYXRPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgZmxvYXQgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmbG9hdCBnZXRNYXBJbnQzMkZsb2F0T3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwSW50MzJGbG9hdCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDQwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJGbG9hdCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJGbG9hdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBmbG9hdCB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwSW50MzJGbG9hdCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gbWFwSW50MzJEb3VibGVfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkgewogICAgICAgIGlmIChtYXBJbnQzMkRvdWJsZV8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJEb3VibGVfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkgewogICAgICAgIGlmIChtYXBJbnQzMkRvdWJsZV8gPT0gbnVsbCkgewogICAgICAgICAgbWFwSW50MzJEb3VibGVfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEludDMyRG91YmxlXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwSW50MzJEb3VibGVfID0gbWFwSW50MzJEb3VibGVfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBJbnQzMkRvdWJsZV87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkRvdWJsZUNvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkRvdWJsZSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkRvdWJsZU1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGdldE1hcEludDMyRG91YmxlKCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQzMkRvdWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGdldE1hcEludDMyRG91YmxlTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZG91YmxlIGdldE1hcEludDMyRG91YmxlT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGRvdWJsZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEludDMyRG91YmxlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwODAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBJbnQzMkRvdWJsZSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJEb3VibGUoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgZG91YmxlIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQzMkRvdWJsZSgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gbWFwQm9vbEJvb2xfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpIHsKICAgICAgICBpZiAobWFwQm9vbEJvb2xfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwQm9vbEJvb2xEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEJvb2xCb29sXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKSB7CiAgICAgICAgaWYgKG1hcEJvb2xCb29sXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBCb29sQm9vbF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwQm9vbEJvb2xfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBCb29sQm9vbF8gPSBtYXBCb29sQm9vbF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEJvb2xCb29sXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEJvb2xCb29sQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEJvb2xCb29sKAogICAgICAgICAgYm9vbGVhbiBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBCb29sQm9vbE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBnZXRNYXBCb29sQm9vbCgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwQm9vbEJvb2xNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gZ2V0TWFwQm9vbEJvb2xNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGdldE1hcEJvb2xCb29sT3JEZWZhdWx0KAogICAgICAgICAgYm9vbGVhbiBrZXksCiAgICAgICAgICBib29sZWFuIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGdldE1hcEJvb2xCb29sT3JUaHJvdygKICAgICAgICAgIGJvb2xlYW4ga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEJvb2xCb29sKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAxMDAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBCb29sQm9vbCgKICAgICAgICAgIGJvb2xlYW4ga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwQm9vbEJvb2woKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBCb29sQm9vbCgKICAgICAgICAgIGJvb2xlYW4ga2V5LAogICAgICAgICAgYm9vbGVhbiB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwQm9vbEJvb2woCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gbWFwU3RyaW5nU3RyaW5nXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpIHsKICAgICAgICBpZiAobWFwU3RyaW5nU3RyaW5nXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFN0cmluZ1N0cmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwU3RyaW5nU3RyaW5nXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpIHsKICAgICAgICBpZiAobWFwU3RyaW5nU3RyaW5nXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBTdHJpbmdTdHJpbmdfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTdHJpbmdTdHJpbmdEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBTdHJpbmdTdHJpbmdfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBTdHJpbmdTdHJpbmdfID0gbWFwU3RyaW5nU3RyaW5nXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwU3RyaW5nU3RyaW5nXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcFN0cmluZ1N0cmluZ0NvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTdHJpbmdTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFN0cmluZ1N0cmluZ01hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0TWFwU3RyaW5nU3RyaW5nKCkgewogICAgICAgIHJldHVybiBnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KamF2YS5sYW5nLlN0cmluZyBnZXRNYXBTdHJpbmdTdHJpbmdPckRlZmF1bHQoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSwKICAgICAgICAgIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZGVmYXVsdFZhbHVlKSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0TWFwU3RyaW5nU3RyaW5nT3JUaHJvdygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBTdHJpbmdTdHJpbmcoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDIwMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcFN0cmluZ1N0cmluZygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDIwMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcFN0cmluZ1N0cmluZygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5LAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIHZhbHVlIik7IH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDIwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBTdHJpbmdTdHJpbmcoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBtYXBJbnQzMkJ5dGVzXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKSB7CiAgICAgICAgaWYgKG1hcEludDMyQnl0ZXNfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJCeXRlc187CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkgewogICAgICAgIGlmIChtYXBJbnQzMkJ5dGVzXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBJbnQzMkJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEludDMyQnl0ZXNfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBJbnQzMkJ5dGVzXyA9IG1hcEludDMyQnl0ZXNfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBJbnQzMkJ5dGVzXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDMyQnl0ZXNDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJCeXRlcygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyQnl0ZXNNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IGdldE1hcEludDMyQnl0ZXMoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEludDMyQnl0ZXNNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBnZXRNYXBJbnQzMkJ5dGVzTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE1hcEludDMyQnl0ZXNPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE1hcEludDMyQnl0ZXNPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQzMkJ5dGVzKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDA0MDAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBJbnQzMkJ5dGVzKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBJbnQzMkJ5dGVzKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewoKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCB2YWx1ZSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwNDAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwSW50MzJCeXRlcygKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcEludDMyRW51bV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpIHsKICAgICAgICBpZiAobWFwSW50MzJFbnVtXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMyRW51bURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJFbnVtXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkgewogICAgICAgIGlmIChtYXBJbnQzMkVudW1fID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMyRW51bV8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMyRW51bURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEludDMyRW51bV8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEludDMyRW51bV8gPSBtYXBJbnQzMkVudW1fLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBJbnQzMkVudW1fOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJFbnVtQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRW51bSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJFbnVtTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZT4KICAgICAgZ2V0TWFwSW50MzJFbnVtKCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQzMkVudW1NYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICAgIGdldE1hcEludDMyRW51bU1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkTWFwSW50MzJFbnVtTWFwKAogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpKTt9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBnZXRNYXBJbnQzMkVudW1PckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpCiAgICAgICAgICAgICAgID8gbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSkKICAgICAgICAgICAgICAgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGdldE1hcEludDMyRW51bU9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQzMkVudW1WYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEludDMyRW51bSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwODAwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJFbnVtKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEludDMyRW51bSgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmdldE11dGFibGVNYXAoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBJbnQzMkVudW0oCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCBtYXBJbnQzMkVudW1WYWx1ZUNvbnZlcnRlci5kb0JhY2t3YXJkKHZhbHVlKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwSW50MzJFbnVtKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRBZGFwdGVkTWFwSW50MzJFbnVtTWFwKAogICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKS5nZXRNdXRhYmxlTWFwKCkpCiAgICAgICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXIuQ29udmVydGVyPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4gewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGJ1aWxkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciB2YWwpIHsKICAgICAgICAgIGlmICh2YWwgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUpIHsgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUpIHZhbDsgfQogICAgICAgICAgcmV0dXJuICgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIpIHZhbCkuYnVpbGQoKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBkZWZhdWx0RW50cnkoKSB7CiAgICAgICAgICByZXR1cm4gTWFwSW50MzJGb3JlaWduTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnk7CiAgICAgICAgfQogICAgICB9OwogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIgPSBuZXcgTWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlcigpOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXI+IG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8PihtYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPD4obWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlcik7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwSW50MzJGb3JlaWduTWVzc2FnZV87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldEltbXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+IG1hcCA9IGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlci5idWlsZChtYXAuZ2V0KGtleSkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+IG1hcCA9IGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIuYnVpbGQobWFwLmdldChrZXkpKTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMTAwMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZU1lc3NhZ2VNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHZhbHVlKSB7CgogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIHZhbHVlIik7IH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwSW50MzJGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGUgOiB2YWx1ZXMuZW50cnlTZXQoKSkgewogICAgICAgICAgaWYgKGUuZ2V0S2V5KCkgPT0gbnVsbCB8fCBlLmdldFZhbHVlKCkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyIHB1dE1hcEludDMyRm9yZWlnbk1lc3NhZ2VCdWlsZGVySWZBYnNlbnQoCiAgICAgICAgICBpbnQga2V5KSB7CiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiBidWlsZGVyTWFwID0gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgZW50cnkgPSBidWlsZGVyTWFwLmdldChrZXkpOwogICAgICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgICAgICBlbnRyeSA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCk7CiAgICAgICAgICBidWlsZGVyTWFwLnB1dChrZXksIGVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKGVudHJ5IGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlKSB7CiAgICAgICAgICBlbnRyeSA9ICgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlKSBlbnRyeSkudG9CdWlsZGVyKCk7CiAgICAgICAgICBidWlsZGVyTWFwLnB1dChrZXksIGVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlcikgZW50cnk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdGVib3JpbmdfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRUZWJvcmluZygpIHsKICAgICAgICBpZiAodGVib3JpbmdfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgVGVib3JpbmdEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRlYm9yaW5nXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKSB7CiAgICAgICAgaWYgKHRlYm9yaW5nXyA9PSBudWxsKSB7CiAgICAgICAgICB0ZWJvcmluZ18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIFRlYm9yaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghdGVib3JpbmdfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICB0ZWJvcmluZ18gPSB0ZWJvcmluZ18uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRlYm9yaW5nXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldFRlYm9yaW5nQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VGVib3JpbmcoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc1RlYm9yaW5nKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldFRlYm9yaW5nTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldFRlYm9yaW5nKCkgewogICAgICAgIHJldHVybiBnZXRUZWJvcmluZ01hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRUZWJvcmluZ01hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRUZWJvcmluZ09yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRUZWJvcmluZ09yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclRlYm9yaW5nKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDIwMDAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVUZWJvcmluZygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgdGVib3JpbmcgPSAxODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVUZWJvcmluZygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldE11dGFibGVUZWJvcmluZygpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZVRlYm9yaW5nKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dFRlYm9yaW5nKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsVGVib3JpbmcoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAyMDAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdE1hcExpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0TWFwTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RNYXBMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RNYXBMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdE1hcExpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWFwTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWFwTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RBcmVuYU1hcExpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMySW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMySW50MzIoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMySW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcEludDMySW50MzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwSW50MzJJbnQzMk1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMySW50MzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMkludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50NjRJbnQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50NjRJbnQ2NCgKICAgICAgICBsb25nIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDY0SW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcEludDY0SW50NjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwSW50NjRJbnQ2NE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBJbnQ2NEludDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwSW50NjRJbnQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwVWludDMyVWludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwVWludDMyVWludDMyKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBVaW50MzJVaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcFVpbnQzMlVpbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwVWludDMyVWludDMyTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFVpbnQzMlVpbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBVaW50MzJVaW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwVWludDY0VWludDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwVWludDY0VWludDY0KAogICAgICAgIGxvbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwVWludDY0VWludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBVaW50NjRVaW50NjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwVWludDY0VWludDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcFVpbnQ2NFVpbnQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ludDMyU2ludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwU2ludDMyU2ludDMyKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTaW50MzJTaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcFNpbnQzMlNpbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwU2ludDMyU2ludDMyTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTaW50MzJTaW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ludDY0U2ludDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwU2ludDY0U2ludDY0KAogICAgICAgIGxvbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ludDY0U2ludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBTaW50NjRTaW50NjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcFNpbnQ2NFNpbnQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEZpeGVkMzJGaXhlZDMyKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwRml4ZWQzMkZpeGVkMzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBGaXhlZDY0Rml4ZWQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBGaXhlZDY0Rml4ZWQ2NCgKICAgICAgICBsb25nIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcEZpeGVkNjRGaXhlZDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFNmaXhlZDMyU2ZpeGVkMzIoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQ2NFNmaXhlZDY0KAogICAgICAgIGxvbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMkZsb2F0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJGbG9hdCgKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJGbG9hdE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgIGdldE1hcEludDMyRmxvYXQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+CiAgICBnZXRNYXBJbnQzMkZsb2F0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgZmxvYXQgZ2V0TWFwSW50MzJGbG9hdE9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGZsb2F0IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgZmxvYXQgZ2V0TWFwSW50MzJGbG9hdE9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMyRG91YmxlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkRvdWJsZSgKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJEb3VibGVNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPgogICAgZ2V0TWFwSW50MzJEb3VibGUoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICBnZXRNYXBJbnQzMkRvdWJsZU1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgZG91YmxlIGdldE1hcEludDMyRG91YmxlT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgZG91YmxlIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBCb29sQm9vbENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwQm9vbEJvb2woCiAgICAgICAgYm9vbGVhbiBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBCb29sQm9vbE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPgogICAgZ2V0TWFwQm9vbEJvb2woKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPgogICAgZ2V0TWFwQm9vbEJvb2xNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gZ2V0TWFwQm9vbEJvb2xPckRlZmF1bHQoCiAgICAgICAgYm9vbGVhbiBrZXksCiAgICAgICAgYm9vbGVhbiBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBnZXRNYXBCb29sQm9vbE9yVGhyb3coCiAgICAgICAgYm9vbGVhbiBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFN0cmluZ1N0cmluZ0NvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBTdHJpbmdTdHJpbmcoCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICBnZXRNYXBTdHJpbmdTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZ2V0TWFwU3RyaW5nU3RyaW5nT3JEZWZhdWx0KAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRNYXBTdHJpbmdTdHJpbmdPclRocm93KAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMyQnl0ZXNDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkJ5dGVzKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkJ5dGVzTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgZ2V0TWFwSW50MzJCeXRlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgIGdldE1hcEludDMyQnl0ZXNNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0TWFwSW50MzJCeXRlc09yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMkVudW1Db3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJFbnVtKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkVudW1NYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgZ2V0TWFwSW50MzJFbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBnZXRNYXBJbnQzMkVudW1NYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBnZXRNYXBJbnQzMkVudW1PckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlICAgICAgICAgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAqLwogICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBnZXRNYXBJbnQzMkVudW1PclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMyRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPgogICAgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+CiAgICBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdEFyZW5hTWFwTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkKICAgICAgVGVzdEFyZW5hTWFwTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdEFyZW5hTWFwTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0QXJlbmFNYXBMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdEFyZW5hTWFwTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0QXJlbmFNYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InJhd3R5cGVzIn0pCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKTsKICAgICAgICBjYXNlIDM6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKTsKICAgICAgICBjYXNlIDQ6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKTsKICAgICAgICBjYXNlIDU6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKTsKICAgICAgICBjYXNlIDY6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKTsKICAgICAgICBjYXNlIDc6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpOwogICAgICAgIGNhc2UgODoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAgICAgY2FzZSA5OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgICAgIGNhc2UgMTA6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCk7CiAgICAgICAgY2FzZSAxMToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKTsKICAgICAgICBjYXNlIDEyOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKTsKICAgICAgICBjYXNlIDEzOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKTsKICAgICAgICBjYXNlIDE0OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCk7CiAgICAgICAgY2FzZSAxNToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKTsKICAgICAgICBjYXNlIDE2OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCk7CiAgICAgICAgY2FzZSAxNzoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKTsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgIH0KICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLmNsYXNzLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQzMkludDMyRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJJbnQzMkVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwSW50MzJJbnQzMl87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkgewogICAgICBpZiAobWFwSW50MzJJbnQzMl8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDMySW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50MzJJbnQzMl87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJJbnQzMigKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJJbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwSW50MzJJbnQzMigpIHsKICAgICAgcmV0dXJuIGdldE1hcEludDMySW50MzJNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwSW50MzJJbnQzMk1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMkludDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMkludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQ2NF9JTlQ2NF9GSUVMRF9OVU1CRVIgPSAyOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50NjRJbnQ2NERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwSW50NjRJbnQ2NF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkgewogICAgICBpZiAobWFwSW50NjRJbnQ2NF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50NjRJbnQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDY0SW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50NjRJbnQ2NCgKICAgICAgICBsb25nIGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDY0SW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEludDY0SW50NjQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQ2NEludDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEludDY0SW50NjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEludDY0SW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEludDY0SW50NjRPclRocm93KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9VSU5UMzJfVUlOVDMyX0ZJRUxEX05VTUJFUiA9IDM7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBVaW50MzJVaW50MzJFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5VSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuVUlOVDMyLAogICAgICAgICAgICAgICAgICAwKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwVWludDMyVWludDMyXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgaWYgKG1hcFVpbnQzMlVpbnQzMl8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcFVpbnQzMlVpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBVaW50MzJVaW50MzJfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBVaW50MzJVaW50MzJDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwVWludDMyVWludDMyKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQzMlVpbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwVWludDMyVWludDMyKCkgewogICAgICByZXR1cm4gZ2V0TWFwVWludDMyVWludDMyTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBVaW50MzJVaW50MzJNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBVaW50MzJVaW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfVUlOVDY0X1VJTlQ2NF9GSUVMRF9OVU1CRVIgPSA0OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuVUlOVDY0LAogICAgICAgICAgICAgICAgICAwTCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5VSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwVWludDY0VWludDY0XzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpIHsKICAgICAgaWYgKG1hcFVpbnQ2NFVpbnQ2NF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcFVpbnQ2NFVpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBVaW50NjRVaW50NjRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBVaW50NjRVaW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwVWludDY0VWludDY0KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBVaW50NjRVaW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFVpbnQ2NFVpbnQ2NCgpIHsKICAgICAgcmV0dXJuIGdldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwVWludDY0VWludDY0TWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBVaW50NjRVaW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcFVpbnQ2NFVpbnQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfU0lOVDMyX1NJTlQzMl9GSUVMRF9OVU1CRVIgPSA1OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU2ludDMyU2ludDMyRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0lOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNJTlQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFNpbnQzMlNpbnQzMl87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgIGlmIChtYXBTaW50MzJTaW50MzJfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwU2ludDMyU2ludDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNpbnQzMlNpbnQzMigKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTaW50MzJTaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNpbnQzMlNpbnQzMigpIHsKICAgICAgcmV0dXJuIGdldE1hcFNpbnQzMlNpbnQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwU2ludDMyU2ludDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX1NJTlQ2NF9TSU5UNjRfRklFTERfTlVNQkVSID0gNjsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcFNpbnQ2NFNpbnQ2NERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNpbnQ2NFNpbnQ2NEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNJTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0lOVDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcFNpbnQ2NFNpbnQ2NF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgIGlmIChtYXBTaW50NjRTaW50NjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwU2ludDY0U2ludDY0XzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDY0U2ludDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNpbnQ2NFNpbnQ2NCgKICAgICAgICBsb25nIGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ludDY0U2ludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTaW50NjRTaW50NjRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBTaW50NjRTaW50NjRPclRocm93KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0ZJWEVEMzJfRklYRUQzMl9GSUVMRF9OVU1CRVIgPSA3OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwRml4ZWQzMkZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkZJWEVEMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRklYRUQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcEZpeGVkMzJGaXhlZDMyXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkgewogICAgICBpZiAobWFwRml4ZWQzMkZpeGVkMzJfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBGaXhlZDMyRml4ZWQzMl87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEZpeGVkMzJGaXhlZDMyKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwRml4ZWQzMkZpeGVkMzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcEZpeGVkMzJGaXhlZDMyKCkgewogICAgICByZXR1cm4gZ2V0TWFwRml4ZWQzMkZpeGVkMzJNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9GSVhFRDY0X0ZJWEVENjRfRklFTERfTlVNQkVSID0gODsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEZpeGVkNjRGaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcEZpeGVkNjRGaXhlZDY0XzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkgewogICAgICBpZiAobWFwRml4ZWQ2NEZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBGaXhlZDY0Rml4ZWQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkNjRGaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEZpeGVkNjRGaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TRklYRUQzMl9TRklYRUQzMl9GSUVMRF9OVU1CRVIgPSA5OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TRklYRUQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TRklYRUQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFNmaXhlZDMyU2ZpeGVkMzJfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpIHsKICAgICAgaWYgKG1hcFNmaXhlZDMyU2ZpeGVkMzJfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFNmaXhlZDMyU2ZpeGVkMzJfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNmaXhlZDMyU2ZpeGVkMzIoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfU0ZJWEVENjRfU0ZJWEVENjRfRklFTERfTlVNQkVSID0gMTA7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNGSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TRklYRUQ2NCwKICAgICAgICAgICAgICAgICAgMEwpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBTZml4ZWQ2NFNmaXhlZDY0XzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKSB7CiAgICAgIGlmIChtYXBTZml4ZWQ2NFNmaXhlZDY0XyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU2ZpeGVkNjRTZml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBTZml4ZWQ2NFNmaXhlZDY0XzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU2ZpeGVkNjRTZml4ZWQ2NCgKICAgICAgICBsb25nIGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRPclRocm93KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9GTE9BVF9GSUVMRF9OVU1CRVIgPSAxMTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyRmxvYXREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GTE9BVCwKICAgICAgICAgICAgICAgICAgMEYpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwSW50MzJGbG9hdF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpIHsKICAgICAgaWYgKG1hcEludDMyRmxvYXRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkZsb2F0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRmxvYXRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMkZsb2F0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZsb2F0KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZsb2F0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZ2V0TWFwSW50MzJGbG9hdCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEludDMyRmxvYXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBnZXRNYXBJbnQzMkZsb2F0TWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZsb2F0IGdldE1hcEludDMyRmxvYXRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBmbG9hdCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZsb2F0IGdldE1hcEludDMyRmxvYXRPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9ET1VCTEVfRklFTERfTlVNQkVSID0gMTI7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkRPVUJMRSwKICAgICAgICAgICAgICAgICAgMEQpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcEludDMyRG91YmxlXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKSB7CiAgICAgIGlmIChtYXBJbnQzMkRvdWJsZV8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDMyRG91YmxlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRG91YmxlXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJEb3VibGVDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRG91YmxlKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJEb3VibGVNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gZ2V0TWFwSW50MzJEb3VibGUoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQzMkRvdWJsZU1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGdldE1hcEludDMyRG91YmxlTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGRvdWJsZSBnZXRNYXBJbnQzMkRvdWJsZU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGRvdWJsZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0JPT0xfQk9PTF9GSUVMRF9OVU1CRVIgPSAxMzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwQm9vbEJvb2xFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5CT09MLAogICAgICAgICAgICAgICAgICBmYWxzZSwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5CT09MLAogICAgICAgICAgICAgICAgICBmYWxzZSk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IG1hcEJvb2xCb29sXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkgewogICAgICBpZiAobWFwQm9vbEJvb2xfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBCb29sQm9vbF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEJvb2xCb29sQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBCb29sQm9vbCgKICAgICAgICBib29sZWFuIGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBCb29sQm9vbE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gZ2V0TWFwQm9vbEJvb2woKSB7CiAgICAgIHJldHVybiBnZXRNYXBCb29sQm9vbE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBnZXRNYXBCb29sQm9vbE1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGdldE1hcEJvb2xCb29sT3JEZWZhdWx0KAogICAgICAgIGJvb2xlYW4ga2V5LAogICAgICAgIGJvb2xlYW4gZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZ2V0TWFwQm9vbEJvb2xPclRocm93KAogICAgICAgIGJvb2xlYW4ga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfU1RSSU5HX1NUUklOR19GSUVMRF9OVU1CRVIgPSAxNDsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcFN0cmluZ1N0cmluZ0RlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU1RSSU5HLAogICAgICAgICAgICAgICAgICAiIiwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TVFJJTkcsCiAgICAgICAgICAgICAgICAgICIiKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcFN0cmluZ1N0cmluZ187CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkgewogICAgICBpZiAobWFwU3RyaW5nU3RyaW5nXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFN0cmluZ1N0cmluZ187CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFN0cmluZ1N0cmluZ0NvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU3RyaW5nU3RyaW5nKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBnZXRNYXBTdHJpbmdTdHJpbmcoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZ2V0TWFwU3RyaW5nU3RyaW5nT3JEZWZhdWx0KAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZGVmYXVsdFZhbHVlKSB7CiAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yVGhyb3coCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0JZVEVTX0ZJRUxEX05VTUJFUiA9IDE1OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJCeXRlc0VudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkJZVEVTLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFkpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwSW50MzJCeXRlc187CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpIHsKICAgICAgaWYgKG1hcEludDMyQnl0ZXNfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyQnl0ZXNfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMkJ5dGVzQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkJ5dGVzKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkJ5dGVzTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZ2V0TWFwSW50MzJCeXRlcygpIHsKICAgICAgcmV0dXJuIGdldE1hcEludDMyQnl0ZXNNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBnZXRNYXBJbnQzMkJ5dGVzTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE1hcEludDMyQnl0ZXNPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9FTlVNX0ZJRUxEX05VTUJFUiA9IDE2OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJFbnVtRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJFbnVtRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRU5VTSwKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZS5NQVBfRU5VTV9GT09fTElURS5nZXROdW1iZXIoKSk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcEludDMyRW51bV87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKSB7CiAgICAgIGlmIChtYXBJbnQzMkVudW1fID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50MzJFbnVtXzsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPiBtYXBJbnQzMkVudW1WYWx1ZUNvbnZlcnRlciA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5uZXdFbnVtQ29udmVydGVyKAogICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZS5pbnRlcm5hbEdldFZhbHVlTWFwKCksCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlLk1BUF9FTlVNX0ZPT19MSVRFKTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBpbnRlcm5hbEdldEFkYXB0ZWRNYXBJbnQzMkVudW1NYXAoCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCkgewogICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlcjwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlLCBqYXZhLmxhbmcuSW50ZWdlcj4oCiAgICAgICAgICAgICAgbWFwLCBtYXBJbnQzMkVudW1WYWx1ZUNvbnZlcnRlcik7CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDMyRW51bUNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJFbnVtKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRW51bU1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgZ2V0TWFwSW50MzJFbnVtKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJFbnVtTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgZ2V0TWFwSW50MzJFbnVtTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkTWFwSW50MzJFbnVtTWFwKAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKSk7fQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBnZXRNYXBJbnQzMkVudW1PckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkKICAgICAgICAgICAgID8gbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSkKICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBnZXRNYXBJbnQzMkVudW1PclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9GT1JFSUdOX01FU1NBR0VfRklFTERfTlVNQkVSID0gMTc7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5NRVNTQUdFLAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPiBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4KICAgIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgaWYgKG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLAogICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplTG9uZ01hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCksCiAgICAgICAgICBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDIpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLAogICAgICAgICAgTWFwVWludDMyVWludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDMpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLAogICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDQpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLAogICAgICAgICAgTWFwU2ludDMyU2ludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDUpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLAogICAgICAgICAgTWFwU2ludDY0U2ludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDYpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCksCiAgICAgICAgICBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICA3KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplTG9uZ01hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLAogICAgICAgICAgTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgOCk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLAogICAgICAgICAgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICA5KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplTG9uZ01hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCksCiAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEwKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCksCiAgICAgICAgICBNYXBJbnQzMkZsb2F0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDExKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLAogICAgICAgICAgTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTIpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVCb29sZWFuTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCksCiAgICAgICAgICBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxMyk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZVN0cmluZ01hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKSwKICAgICAgICAgIE1hcFN0cmluZ1N0cmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxNCk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLAogICAgICAgICAgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxNSk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCksCiAgICAgICAgICBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTYpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSwKICAgICAgICAgIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTcpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBtYXBJbnQzMkludDMyX18gPSBNYXBJbnQzMkludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxLCBtYXBJbnQzMkludDMyX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgbWFwSW50NjRJbnQ2NF9fID0gTWFwSW50NjRJbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMiwgbWFwSW50NjRJbnQ2NF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgbWFwVWludDMyVWludDMyX18gPSBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDMsIG1hcFVpbnQzMlVpbnQzMl9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgbWFwVWludDY0VWludDY0X18gPSBNYXBVaW50NjRVaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDQsIG1hcFVpbnQ2NFVpbnQ2NF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgbWFwU2ludDMyU2ludDMyX18gPSBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDUsIG1hcFNpbnQzMlNpbnQzMl9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgbWFwU2ludDY0U2ludDY0X18gPSBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDYsIG1hcFNpbnQ2NFNpbnQ2NF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBtYXBGaXhlZDMyRml4ZWQzMl9fID0gTWFwRml4ZWQzMkZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDcsIG1hcEZpeGVkMzJGaXhlZDMyX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgIG1hcEZpeGVkNjRGaXhlZDY0X18gPSBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoOCwgbWFwRml4ZWQ2NEZpeGVkNjRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBtYXBTZml4ZWQzMlNmaXhlZDMyX18gPSBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg5LCBtYXBTZml4ZWQzMlNmaXhlZDMyX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgbWFwU2ZpeGVkNjRTZml4ZWQ2NF9fID0gTWFwU2ZpeGVkNjRTZml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTAsIG1hcFNmaXhlZDY0U2ZpeGVkNjRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgICAgIG1hcEludDMyRmxvYXRfXyA9IE1hcEludDMyRmxvYXREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDExLCBtYXBJbnQzMkZsb2F0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgICAgICBtYXBJbnQzMkRvdWJsZV9fID0gTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEyLCBtYXBJbnQzMkRvdWJsZV9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgICAgICBtYXBCb29sQm9vbF9fID0gTWFwQm9vbEJvb2xEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEzLCBtYXBCb29sQm9vbF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgICAgICBtYXBTdHJpbmdTdHJpbmdfXyA9IE1hcFN0cmluZ1N0cmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTQsIG1hcFN0cmluZ1N0cmluZ19fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICAgICAgbWFwSW50MzJCeXRlc19fID0gTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTUsIG1hcEludDMyQnl0ZXNfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcEludDMyRW51bV9fID0gTWFwSW50MzJFbnVtRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxNiwgbWFwSW50MzJFbnVtX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPgogICAgICAgIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfXyA9IE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE3LCBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlX18pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIG90aGVyID0gKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMySW50MzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDY0SW50NjQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwQm9vbEJvb2woKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRW51bSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDY0X0lOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfVUlOVDMyX1VJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfVUlOVDY0X1VJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfU0lOVDMyX1NJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfU0lOVDY0X1NJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9GSVhFRDMyX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9GSVhFRDY0X0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1NGSVhFRDMyX1NGSVhFRDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1NGSVhFRDY0X1NGSVhFRDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0ZMT0FUX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQzMl9ET1VCTEVfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9CT09MX0JPT0xfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfU1RSSU5HX1NUUklOR19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0JZVEVTX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UMzJfRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0ZPUkVJR05fTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICAgIGludCBudW1iZXIpIHsKICAgICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCk7CiAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKTsKICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCk7CiAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpOwogICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKTsKICAgICAgICAgIGNhc2UgNjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCk7CiAgICAgICAgICBjYXNlIDc6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAgICAgICBjYXNlIDk6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKTsKICAgICAgICAgIGNhc2UgMTA6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKTsKICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKTsKICAgICAgICAgIGNhc2UgMTI6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCk7CiAgICAgICAgICBjYXNlIDEzOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpOwogICAgICAgICAgY2FzZSAxNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCk7CiAgICAgICAgICBjYXNlIDE1OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCk7CiAgICAgICAgICBjYXNlIDE2OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKTsKICAgICAgICAgIGNhc2UgMTc6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCk7CiAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCk7CiAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKTsKICAgICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpOwogICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCk7CiAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKTsKICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpOwogICAgICAgICAgY2FzZSA5OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgICAgICAgY2FzZSAxMDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKTsKICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCk7CiAgICAgICAgICBjYXNlIDEyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKTsKICAgICAgICAgIGNhc2UgMTM6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpOwogICAgICAgICAgY2FzZSAxNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpOwogICAgICAgICAgY2FzZSAxNToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKTsKICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKTsKICAgICAgICAgIGNhc2UgMTc6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuY2xhc3MsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgYnVpbGQoKSB7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcmVzdWx0ID0gbmV3IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkludDMyXyA9IGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMySW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQ2NEludDY0XyA9IGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDY0SW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50MzJVaW50MzJfID0gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKTsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50MzJVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50NjRVaW50NjRfID0gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50NjRVaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50MzJTaW50MzJfID0gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50MzJTaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50NjRTaW50NjRfID0gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50NjRTaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBGaXhlZDMyRml4ZWQzMl8gPSBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgICByZXN1bHQubWFwRml4ZWQzMkZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA4MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBGaXhlZDY0Rml4ZWQ2NF8gPSBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAgICAgICByZXN1bHQubWFwRml4ZWQ2NEZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTZml4ZWQzMlNmaXhlZDMyXyA9IGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgICAgICAgcmVzdWx0Lm1hcFNmaXhlZDMyU2ZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTZml4ZWQ2NFNmaXhlZDY0XyA9IGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpOwogICAgICAgICAgcmVzdWx0Lm1hcFNmaXhlZDY0U2ZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDQwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkZsb2F0XyA9IGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMyRmxvYXRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDgwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkRvdWJsZV8gPSBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCk7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJEb3VibGVfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBCb29sQm9vbF8gPSBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCk7CiAgICAgICAgICByZXN1bHQubWFwQm9vbEJvb2xfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTdHJpbmdTdHJpbmdfID0gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTdHJpbmdTdHJpbmdfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwNDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkJ5dGVzXyA9IGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMyQnl0ZXNfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwODAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkVudW1fID0gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKTsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkVudW1fLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAxMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkZvcmVpZ25NZXNzYWdlXyA9IGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmJ1aWxkKE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMySW50MzIoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwQm9vbEJvb2woKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJCeXRlcygpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRW51bSgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDEwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIG1hcEludDMySW50MzJfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcEludDMySW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwSW50MzJJbnQzMl9fLmdldEtleSgpLCBtYXBJbnQzMkludDMyX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTAKICAgICAgICAgICAgICBjYXNlIDE4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgICAgICAgIG1hcEludDY0SW50NjRfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwSW50NjRJbnQ2NF9fLmdldEtleSgpLCBtYXBJbnQ2NEludDY0X18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTgKICAgICAgICAgICAgICBjYXNlIDI2OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIG1hcFVpbnQzMlVpbnQzMl9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwVWludDMyVWludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwVWludDMyVWludDMyX18uZ2V0S2V5KCksIG1hcFVpbnQzMlVpbnQzMl9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI2CiAgICAgICAgICAgICAgY2FzZSAzNDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICAgICAgICBtYXBVaW50NjRVaW50NjRfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcFVpbnQ2NFVpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFVpbnQ2NFVpbnQ2NF9fLmdldEtleSgpLCBtYXBVaW50NjRVaW50NjRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzNAogICAgICAgICAgICAgIGNhc2UgNDI6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwU2ludDMyU2ludDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBTaW50MzJTaW50MzJfXy5nZXRLZXkoKSwgbWFwU2ludDMyU2ludDMyX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDIKICAgICAgICAgICAgICBjYXNlIDUwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgICAgICAgIG1hcFNpbnQ2NFNpbnQ2NF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwU2ludDY0U2ludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwU2ludDY0U2ludDY0X18uZ2V0S2V5KCksIG1hcFNpbnQ2NFNpbnQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDUwCiAgICAgICAgICAgICAgY2FzZSA1ODogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBtYXBGaXhlZDMyRml4ZWQzMl9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwRml4ZWQzMkZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEZpeGVkMzJGaXhlZDMyX18uZ2V0S2V5KCksIG1hcEZpeGVkMzJGaXhlZDMyX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTgKICAgICAgICAgICAgICBjYXNlIDY2OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgICAgICAgIG1hcEZpeGVkNjRGaXhlZDY0X18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwRml4ZWQ2NEZpeGVkNjRfXy5nZXRLZXkoKSwgbWFwRml4ZWQ2NEZpeGVkNjRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA2NgogICAgICAgICAgICAgIGNhc2UgNzQ6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwU2ZpeGVkMzJTZml4ZWQzMl9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBTZml4ZWQzMlNmaXhlZDMyX18uZ2V0S2V5KCksIG1hcFNmaXhlZDMyU2ZpeGVkMzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3NAogICAgICAgICAgICAgIGNhc2UgODI6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwU2ZpeGVkNjRTZml4ZWQ2NF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwU2ZpeGVkNjRTZml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBTZml4ZWQ2NFNmaXhlZDY0X18uZ2V0S2V5KCksIG1hcFNmaXhlZDY0U2ZpeGVkNjRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4MgogICAgICAgICAgICAgIGNhc2UgOTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgICAgICAgICAgICAgIG1hcEludDMyRmxvYXRfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcEludDMyRmxvYXREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwSW50MzJGbG9hdF9fLmdldEtleSgpLCBtYXBJbnQzMkZsb2F0X18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTAKICAgICAgICAgICAgICBjYXNlIDk4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPgogICAgICAgICAgICAgICAgbWFwSW50MzJEb3VibGVfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcEludDMyRG91YmxlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkRvdWJsZV9fLmdldEtleSgpLCBtYXBJbnQzMkRvdWJsZV9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDk4CiAgICAgICAgICAgICAgY2FzZSAxMDY6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgICAgICAgICAgbWFwQm9vbEJvb2xfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBCb29sQm9vbF9fLmdldEtleSgpLCBtYXBCb29sQm9vbF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEwNgogICAgICAgICAgICAgIGNhc2UgMTE0OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICAgICAgICAgICAgICBtYXBTdHJpbmdTdHJpbmdfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcFN0cmluZ1N0cmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFN0cmluZ1N0cmluZ19fLmdldEtleSgpLCBtYXBTdHJpbmdTdHJpbmdfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMTQKICAgICAgICAgICAgICBjYXNlIDEyMjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgICAgICAgICAgICAgbWFwSW50MzJCeXRlc19fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkJ5dGVzX18uZ2V0S2V5KCksIG1hcEludDMyQnl0ZXNfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwNDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMjIKICAgICAgICAgICAgICBjYXNlIDEzMDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJ5dGVzID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIG1hcEludDMyRW51bV9fID0gTWFwSW50MzJFbnVtRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCkucGFyc2VGcm9tKGJ5dGVzKTsKICAgICAgICAgICAgICAgIGlmIChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlLmZvck51bWJlcihtYXBJbnQzMkVudW1fXy5nZXRWYWx1ZSgpKSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93bkxlbmd0aERlbGltaXRlZEZpZWxkKDE2LCBieXRlcyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgICAgbWFwSW50MzJFbnVtX18uZ2V0S2V5KCksIG1hcEludDMyRW51bV9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTMwCiAgICAgICAgICAgICAgY2FzZSAxMzg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+CiAgICAgICAgICAgICAgICBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfXy5nZXRLZXkoKSwgbWFwSW50MzJGb3JlaWduTWVzc2FnZV9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEzOAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcEludDMySW50MzJfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkgewogICAgICAgIGlmIChtYXBJbnQzMkludDMyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMySW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMySW50MzJfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkgewogICAgICAgIGlmIChtYXBJbnQzMkludDMyXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBJbnQzMkludDMyXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEludDMySW50MzJfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBJbnQzMkludDMyXyA9IG1hcEludDMySW50MzJfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBJbnQzMkludDMyXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkludDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJJbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBJbnQzMkludDMyKCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQzMkludDMyTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcEludDMySW50MzJNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkludDMyT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJJbnQzMk9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwSW50MzJJbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBJbnQzMkludDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJJbnQzMigKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwSW50MzJJbnQzMigKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwSW50NjRJbnQ2NF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKSB7CiAgICAgICAgaWYgKG1hcEludDY0SW50NjRfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50NjRJbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50NjRJbnQ2NF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKSB7CiAgICAgICAgaWYgKG1hcEludDY0SW50NjRfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDY0SW50NjRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwSW50NjRJbnQ2NF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEludDY0SW50NjRfID0gbWFwSW50NjRJbnQ2NF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDY0SW50NjRfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50NjRJbnQ2NENvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDY0SW50NjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50NjRJbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBJbnQ2NEludDY0KCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQ2NEludDY0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEludDY0SW50NjRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwSW50NjRJbnQ2NE9yRGVmYXVsdCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcEludDY0SW50NjRPclRocm93KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQ2NEludDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEludDY0SW50NjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50NjRJbnQ2NCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQ2NEludDY0KAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBVaW50MzJVaW50MzJfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKSB7CiAgICAgICAgaWYgKG1hcFVpbnQzMlVpbnQzMl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcFVpbnQzMlVpbnQzMl87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgICBpZiAobWFwVWludDMyVWludDMyXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBVaW50MzJVaW50MzJfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBVaW50MzJVaW50MzJfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBVaW50MzJVaW50MzJfID0gbWFwVWludDMyVWludDMyXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwVWludDMyVWludDMyXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQzMlVpbnQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFVpbnQzMlVpbnQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwVWludDMyVWludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwVWludDMyVWludDMyTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBVaW50MzJVaW50MzJNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBVaW50MzJVaW50MzJPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBVaW50MzJVaW50MzJPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwVWludDMyVWludDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcFVpbnQzMlVpbnQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBVaW50MzJVaW50MzIoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcFVpbnQzMlVpbnQzMigKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBVaW50NjRVaW50NjRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKSB7CiAgICAgICAgaWYgKG1hcFVpbnQ2NFVpbnQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBVaW50NjRVaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcFVpbnQ2NFVpbnQ2NF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpIHsKICAgICAgICBpZiAobWFwVWludDY0VWludDY0XyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBVaW50NjRVaW50NjRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBVaW50NjRVaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBVaW50NjRVaW50NjRfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBVaW50NjRVaW50NjRfID0gbWFwVWludDY0VWludDY0Xy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwVWludDY0VWludDY0XzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQ2NFVpbnQ2NENvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFVpbnQ2NFVpbnQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBVaW50NjRVaW50NjQoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwVWludDY0VWludDY0TWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcFVpbnQ2NFVpbnQ2NE9yRGVmYXVsdCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcFVpbnQ2NFVpbnQ2NE9yVGhyb3coCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwVWludDY0VWludDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcFVpbnQ2NFVpbnQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwVWludDY0VWludDY0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcFVpbnQ2NFVpbnQ2NCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBTaW50MzJTaW50MzJfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgICAgaWYgKG1hcFNpbnQzMlNpbnQzMl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcFNpbnQzMlNpbnQzMl87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpIHsKICAgICAgICBpZiAobWFwU2ludDMyU2ludDMyXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBTaW50MzJTaW50MzJfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBTaW50MzJTaW50MzJfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBTaW50MzJTaW50MzJfID0gbWFwU2ludDMyU2ludDMyXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwU2ludDMyU2ludDMyXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQzMlNpbnQzMkNvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNpbnQzMlNpbnQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ludDMyU2ludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNpbnQzMlNpbnQzMigpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwU2ludDMyU2ludDMyTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTaW50MzJTaW50MzJNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBTaW50MzJTaW50MzJPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBTaW50MzJTaW50MzJPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwU2ludDMyU2ludDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcFNpbnQzMlNpbnQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBTaW50MzJTaW50MzIoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcFNpbnQzMlNpbnQzMigKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBTaW50NjRTaW50NjRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgICAgaWYgKG1hcFNpbnQ2NFNpbnQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcFNpbnQ2NFNpbnQ2NF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpIHsKICAgICAgICBpZiAobWFwU2ludDY0U2ludDY0XyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBTaW50NjRTaW50NjRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBTaW50NjRTaW50NjRfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBTaW50NjRTaW50NjRfID0gbWFwU2ludDY0U2ludDY0Xy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwU2ludDY0U2ludDY0XzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQ2NFNpbnQ2NENvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNpbnQ2NFNpbnQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ludDY0U2ludDY0TWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcFNpbnQ2NFNpbnQ2NE9yRGVmYXVsdCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcFNpbnQ2NFNpbnQ2NE9yVGhyb3coCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwU2ludDY0U2ludDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDIwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcFNpbnQ2NFNpbnQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwU2ludDY0U2ludDY0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcFNpbnQ2NFNpbnQ2NCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBGaXhlZDMyRml4ZWQzMl87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkgewogICAgICAgIGlmIChtYXBGaXhlZDMyRml4ZWQzMl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwRml4ZWQzMkZpeGVkMzJfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpIHsKICAgICAgICBpZiAobWFwRml4ZWQzMkZpeGVkMzJfID09IG51bGwpIHsKICAgICAgICAgIG1hcEZpeGVkMzJGaXhlZDMyXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwRml4ZWQzMkZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBGaXhlZDMyRml4ZWQzMl8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEZpeGVkMzJGaXhlZDMyXyA9IG1hcEZpeGVkMzJGaXhlZDMyXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwRml4ZWQzMkZpeGVkMzJfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBGaXhlZDMyRml4ZWQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBGaXhlZDMyRml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwRml4ZWQzMkZpeGVkMzJNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBGaXhlZDMyRml4ZWQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBGaXhlZDMyRml4ZWQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEZpeGVkMzJGaXhlZDMyKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwRml4ZWQ2NEZpeGVkNjRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgICBpZiAobWFwRml4ZWQ2NEZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEZpeGVkNjRGaXhlZDY0XzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKSB7CiAgICAgICAgaWYgKG1hcEZpeGVkNjRGaXhlZDY0XyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBGaXhlZDY0Rml4ZWQ2NF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEZpeGVkNjRGaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwRml4ZWQ2NEZpeGVkNjRfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBGaXhlZDY0Rml4ZWQ2NF8gPSBtYXBGaXhlZDY0Rml4ZWQ2NF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEZpeGVkNjRGaXhlZDY0XzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkNjRGaXhlZDY0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwRml4ZWQ2NEZpeGVkNjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEZpeGVkNjRGaXhlZDY0KCkgewogICAgICAgIHJldHVybiBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcEZpeGVkNjRGaXhlZDY0T3JEZWZhdWx0KAogICAgICAgICAgbG9uZyBrZXksCiAgICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRPclRocm93KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwRml4ZWQ2NEZpeGVkNjQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwODApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwRml4ZWQ2NEZpeGVkNjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBGaXhlZDY0Rml4ZWQ2NCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBGaXhlZDY0Rml4ZWQ2NCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFNmaXhlZDMyU2ZpeGVkMzJfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkgewogICAgICAgIGlmIChtYXBTZml4ZWQzMlNmaXhlZDMyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFNmaXhlZDMyU2ZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcFNmaXhlZDMyU2ZpeGVkMzJfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkgewogICAgICAgIGlmIChtYXBTZml4ZWQzMlNmaXhlZDMyXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBTZml4ZWQzMlNmaXhlZDMyXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcFNmaXhlZDMyU2ZpeGVkMzJfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBTZml4ZWQzMlNmaXhlZDMyXyA9IG1hcFNmaXhlZDMyU2ZpeGVkMzJfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBTZml4ZWQzMlNmaXhlZDMyXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQzMlNmaXhlZDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkgewogICAgICAgIHJldHVybiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwU2ZpeGVkMzJTZml4ZWQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDEwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBTZml4ZWQzMlNmaXhlZDMyKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwU2ZpeGVkMzJTZml4ZWQzMigKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwU2ZpeGVkMzJTZml4ZWQzMigKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwU2ZpeGVkNjRTZml4ZWQ2NF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKSB7CiAgICAgICAgaWYgKG1hcFNmaXhlZDY0U2ZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU2ZpeGVkNjRTZml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwU2ZpeGVkNjRTZml4ZWQ2NF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKSB7CiAgICAgICAgaWYgKG1hcFNmaXhlZDY0U2ZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICAgIG1hcFNmaXhlZDY0U2ZpeGVkNjRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwU2ZpeGVkNjRTZml4ZWQ2NF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcFNmaXhlZDY0U2ZpeGVkNjRfID0gbWFwU2ZpeGVkNjRTZml4ZWQ2NF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NENvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQ2NFNmaXhlZDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE9yRGVmYXVsdCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0T3JUaHJvdygKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDIwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwU2ZpeGVkNjRTZml4ZWQ2NCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IG1hcEludDMyRmxvYXRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpIHsKICAgICAgICBpZiAobWFwSW50MzJGbG9hdF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkZsb2F0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQzMkZsb2F0XzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKSB7CiAgICAgICAgaWYgKG1hcEludDMyRmxvYXRfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMyRmxvYXRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkZsb2F0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwSW50MzJGbG9hdF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEludDMyRmxvYXRfID0gbWFwSW50MzJGbG9hdF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDMyRmxvYXRfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJGbG9hdENvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZsb2F0KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJGbG9hdE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZ2V0TWFwSW50MzJGbG9hdCgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwSW50MzJGbG9hdE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IGdldE1hcEludDMyRmxvYXRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmbG9hdCBnZXRNYXBJbnQzMkZsb2F0T3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGZsb2F0IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmxvYXQgZ2V0TWFwSW50MzJGbG9hdE9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEludDMyRmxvYXQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDA0MDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEludDMyRmxvYXQoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwSW50MzJGbG9hdCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEludDMyRmxvYXQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgZmxvYXQgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEludDMyRmxvYXQoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcEludDMyRG91YmxlXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpIHsKICAgICAgICBpZiAobWFwSW50MzJEb3VibGVfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyRG91YmxlXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpIHsKICAgICAgICBpZiAobWFwSW50MzJEb3VibGVfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMyRG91YmxlXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBJbnQzMkRvdWJsZV8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEludDMyRG91YmxlXyA9IG1hcEludDMyRG91YmxlXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwSW50MzJEb3VibGVfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJEb3VibGVDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJEb3VibGUoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJEb3VibGVNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBnZXRNYXBJbnQzMkRvdWJsZSgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwSW50MzJEb3VibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBnZXRNYXBJbnQzMkRvdWJsZU1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGRvdWJsZSBnZXRNYXBJbnQzMkRvdWJsZU9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBkb3VibGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZG91YmxlIGdldE1hcEludDMyRG91YmxlT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQzMkRvdWJsZSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDgwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJEb3VibGUoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEludDMyRG91YmxlKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGRvdWJsZSB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwSW50MzJEb3VibGUoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IG1hcEJvb2xCb29sXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgICAgICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKSB7CiAgICAgICAgaWYgKG1hcEJvb2xCb29sXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBCb29sQm9vbF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkgewogICAgICAgIGlmIChtYXBCb29sQm9vbF8gPT0gbnVsbCkgewogICAgICAgICAgbWFwQm9vbEJvb2xfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEJvb2xCb29sXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwQm9vbEJvb2xfID0gbWFwQm9vbEJvb2xfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBCb29sQm9vbF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBCb29sQm9vbENvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBCb29sQm9vbCgKICAgICAgICAgIGJvb2xlYW4ga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwQm9vbEJvb2xNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gZ2V0TWFwQm9vbEJvb2woKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEJvb2xCb29sTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGdldE1hcEJvb2xCb29sTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBnZXRNYXBCb29sQm9vbE9yRGVmYXVsdCgKICAgICAgICAgIGJvb2xlYW4ga2V5LAogICAgICAgICAgYm9vbGVhbiBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBnZXRNYXBCb29sQm9vbE9yVGhyb3coCiAgICAgICAgICBib29sZWFuIGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBCb29sQm9vbCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMTAwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwQm9vbEJvb2woCiAgICAgICAgICBib29sZWFuIGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEJvb2xCb29sKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwQm9vbEJvb2woCiAgICAgICAgICBib29sZWFuIGtleSwKICAgICAgICAgIGJvb2xlYW4gdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEJvb2xCb29sKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcFN0cmluZ1N0cmluZ187CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKSB7CiAgICAgICAgaWYgKG1hcFN0cmluZ1N0cmluZ18gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTdHJpbmdTdHJpbmdEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcFN0cmluZ1N0cmluZ187CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKSB7CiAgICAgICAgaWYgKG1hcFN0cmluZ1N0cmluZ18gPT0gbnVsbCkgewogICAgICAgICAgbWFwU3RyaW5nU3RyaW5nXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwU3RyaW5nU3RyaW5nXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwU3RyaW5nU3RyaW5nXyA9IG1hcFN0cmluZ1N0cmluZ18uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDIwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcFN0cmluZ1N0cmluZ187CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBTdHJpbmdTdHJpbmdDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU3RyaW5nU3RyaW5nKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IGdldE1hcFN0cmluZ1N0cmluZygpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IGdldE1hcFN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZ2V0TWFwU3RyaW5nU3RyaW5nT3JEZWZhdWx0KAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yVGhyb3coCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwU3RyaW5nU3RyaW5nKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBTdHJpbmdTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgICAgICAgIGdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBTdHJpbmdTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSwKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCB2YWx1ZSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwU3RyaW5nU3RyaW5nKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwSW50MzJCeXRlc187CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkgewogICAgICAgIGlmIChtYXBJbnQzMkJ5dGVzXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMyQnl0ZXNEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyQnl0ZXNfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpIHsKICAgICAgICBpZiAobWFwSW50MzJCeXRlc18gPT0gbnVsbCkgewogICAgICAgICAgbWFwSW50MzJCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMyQnl0ZXNEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBJbnQzMkJ5dGVzXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwSW50MzJCeXRlc18gPSBtYXBJbnQzMkJ5dGVzXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwNDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwSW50MzJCeXRlc187CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkJ5dGVzQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyQnl0ZXMoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkJ5dGVzTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBnZXRNYXBJbnQzMkJ5dGVzKCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQzMkJ5dGVzTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZ2V0TWFwSW50MzJCeXRlc01hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwSW50MzJCeXRlcygpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwNDAwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJCeXRlcygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwNDAwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJCeXRlcygKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKCiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAgdmFsdWUiKTsgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEludDMyQnl0ZXMoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwNDAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBJbnQzMkVudW1fOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKSB7CiAgICAgICAgaWYgKG1hcEludDMyRW51bV8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyRW51bV87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpIHsKICAgICAgICBpZiAobWFwSW50MzJFbnVtXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBJbnQzMkVudW1fID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBJbnQzMkVudW1fLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBJbnQzMkVudW1fID0gbWFwSW50MzJFbnVtXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwSW50MzJFbnVtXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDMyRW51bUNvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkVudW0oCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRW51bU1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICAgIGdldE1hcEludDMyRW51bSgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwSW50MzJFbnVtTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgICBnZXRNYXBJbnQzMkVudW1NYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKSk7fQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgICA/IG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBnZXRNYXBJbnQzMkVudW1PclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQzMkVudW0oKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDgwMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEludDMyRW51bSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkVudW0oKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRNYXBJbnQzMkVudW1NYXAoCiAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKS5nZXRNdXRhYmxlTWFwKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJFbnVtKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9CYWNrd2FyZCh2YWx1ZSkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEludDMyRW51bSgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpKQogICAgICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlciBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyLkNvbnZlcnRlcjxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZU9yQnVpbGRlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBidWlsZChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlT3JCdWlsZGVyIHZhbCkgewogICAgICAgICAgaWYgKHZhbCBpbnN0YW5jZW9mIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUpIHsgcmV0dXJuIChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKSB2YWw7IH0KICAgICAgICAgIHJldHVybiAoKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuQnVpbGRlcikgdmFsKS5idWlsZCgpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPiBkZWZhdWx0RW50cnkoKSB7CiAgICAgICAgICByZXR1cm4gTWFwSW50MzJGb3JlaWduTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnk7CiAgICAgICAgfQogICAgICB9OwogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIgPSBuZXcgTWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlcigpOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlT3JCdWlsZGVyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLkJ1aWxkZXI+IG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlT3JCdWlsZGVyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLkJ1aWxkZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8PihtYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuQnVpbGRlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPD4obWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlcik7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwSW50MzJGb3JlaWduTWVzc2FnZV87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPiBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldEltbXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZU9yQnVpbGRlcj4gbWFwID0gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyLmJ1aWxkKG1hcC5nZXQoa2V5KSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXI+IG1hcCA9IGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIuYnVpbGQobWFwLmdldChrZXkpKTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMTAwMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZU1lc3NhZ2VNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIHZhbHVlKSB7CgogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIHZhbHVlIik7IH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPiBlIDogdmFsdWVzLmVudHJ5U2V0KCkpIHsKICAgICAgICAgIGlmIChlLmdldEtleSgpID09IG51bGwgfHwgZS5nZXRWYWx1ZSgpID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuQnVpbGRlciBwdXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQnVpbGRlcklmQWJzZW50KAogICAgICAgICAgaW50IGtleSkgewogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXI+IGJ1aWxkZXJNYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpOwogICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXIgZW50cnkgPSBidWlsZGVyTWFwLmdldChrZXkpOwogICAgICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgICAgICBlbnRyeSA9IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUubmV3QnVpbGRlcigpOwogICAgICAgICAgYnVpbGRlck1hcC5wdXQoa2V5LCBlbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmIChlbnRyeSBpbnN0YW5jZW9mIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUpIHsKICAgICAgICAgIGVudHJ5ID0gKChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKSBlbnRyeSkudG9CdWlsZGVyKCk7CiAgICAgICAgICBidWlsZGVyTWFwLnB1dChrZXksIGVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLkJ1aWxkZXIpIGVudHJ5OwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RBcmVuYU1hcExpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdEFyZW5hTWFwTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RBcmVuYU1hcExpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0QXJlbmFNYXBMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RBcmVuYU1hcExpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEZpZWxkQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwRmllbGQoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPgogICAgZ2V0TWFwRmllbGQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+CiAgICBnZXRNYXBGaWVsZE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBnZXRNYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBnZXRNYXBGaWVsZE9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CiAgfQogIC8qKgogICAqIDxwcmU+CiAgICogVGVzdCBlbWJlZGRlZCBtZXNzYWdlIHdpdGggcmVxdWlyZWQgZmllbGRzCiAgICogPC9wcmU+CiAgICoKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUpCiAgICAgIFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgaW50IG51bWJlcikgewogICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpZWxkKCk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICB9CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlLmNsYXNzLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9GSUVMRF9GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZV9NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLk1FU1NBR0UsCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPiBtYXBGaWVsZF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4KICAgIGludGVybmFsR2V0TWFwRmllbGQoKSB7CiAgICAgIGlmIChtYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEZpZWxkXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwRmllbGRDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRmllbGQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBGaWVsZCgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gZ2V0TWFwRmllbGQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBGaWVsZE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IGdldE1hcEZpZWxkTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgZ2V0TWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIGdldE1hcEZpZWxkT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgZm9yIChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgaXRlbSA6IGdldE1hcEZpZWxkTWFwKCkudmFsdWVzKCkpIHsKICAgICAgICBpZiAoIWl0ZW0uaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwRmllbGQoKSwKICAgICAgICAgIE1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEZpZWxkKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4KICAgICAgICBtYXBGaWVsZF9fID0gTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEsIG1hcEZpZWxkX18pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgb3RoZXIgPSAocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEZpZWxkKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBGaWVsZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogVGVzdCBlbWJlZGRlZCBtZXNzYWdlIHdpdGggcmVxdWlyZWQgZmllbGRzCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUpCiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICAgIGludCBudW1iZXIpIHsKICAgICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaWVsZCgpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZS5jbGFzcywgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBidWlsZCgpIHsKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSByZXN1bHQgPSBuZXcgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwRmllbGRfID0gaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmJ1aWxkKE1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEZpZWxkKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgZm9yIChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgaXRlbSA6IGdldE1hcEZpZWxkTWFwKCkudmFsdWVzKCkpIHsKICAgICAgICAgIGlmICghaXRlbS5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4KICAgICAgICAgICAgICAgIG1hcEZpZWxkX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZCgpLmVuc3VyZUJ1aWxkZXJNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwRmllbGRfXy5nZXRLZXkoKSwgbWFwRmllbGRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBGaWVsZENvbnZlcnRlciBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyLkNvbnZlcnRlcjxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IHsKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBidWlsZChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXIgdmFsKSB7CiAgICAgICAgICBpZiAodmFsIGluc3RhbmNlb2YgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlKSB7IHJldHVybiAocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlKSB2YWw7IH0KICAgICAgICAgIHJldHVybiAoKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5CdWlsZGVyKSB2YWwpLmJ1aWxkKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gZGVmYXVsdEVudHJ5KCkgewogICAgICAgICAgcmV0dXJuIE1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIE1hcEZpZWxkQ29udmVydGVyIG1hcEZpZWxkQ29udmVydGVyID0gbmV3IE1hcEZpZWxkQ29udmVydGVyKCk7CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZU9yQnVpbGRlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuQnVpbGRlcj4gbWFwRmllbGRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLkJ1aWxkZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpZWxkKCkgewogICAgICAgIGlmIChtYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjw+KG1hcEZpZWxkQ29udmVydGVyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEZpZWxkXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLkJ1aWxkZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZCgpIHsKICAgICAgICBpZiAobWFwRmllbGRfID09IG51bGwpIHsKICAgICAgICAgIG1hcEZpZWxkXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjw+KG1hcEZpZWxkQ29udmVydGVyKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBGaWVsZF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBGaWVsZENvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpZWxkKCkuZW5zdXJlQnVpbGRlck1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEZpZWxkKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmVuc3VyZUJ1aWxkZXJNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gZ2V0TWFwRmllbGQoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEZpZWxkTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gZ2V0TWFwRmllbGRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRmllbGQoKS5nZXRJbW11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIGdldE1hcEZpZWxkT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyPiBtYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZCgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXBGaWVsZENvbnZlcnRlci5idWlsZChtYXAuZ2V0KGtleSkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgZ2V0TWFwRmllbGRPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXI+IG1hcCA9IGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkuZW5zdXJlQnVpbGRlck1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBGaWVsZENvbnZlcnRlci5idWlsZChtYXAuZ2V0KGtleSkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwRmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwRmllbGQoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkuZW5zdXJlQnVpbGRlck1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGQoKS5lbnN1cmVNZXNzYWdlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSB2YWx1ZSkgewoKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCB2YWx1ZSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGQoKS5lbnN1cmVCdWlsZGVyTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEZpZWxkKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPiB2YWx1ZXMpIHsKICAgICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gZSA6IHZhbHVlcy5lbnRyeVNldCgpKSB7CiAgICAgICAgICBpZiAoZS5nZXRLZXkoKSA9PSBudWxsIHx8IGUuZ2V0VmFsdWUoKSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZCgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLkJ1aWxkZXIgcHV0TWFwRmllbGRCdWlsZGVySWZBYnNlbnQoCiAgICAgICAgICBpbnQga2V5KSB7CiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyPiBidWlsZGVyTWFwID0gaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGQoKS5lbnN1cmVCdWlsZGVyTWFwKCk7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyIGVudHJ5ID0gYnVpbGRlck1hcC5nZXQoa2V5KTsKICAgICAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICAgICAgZW50cnkgPSBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUubmV3QnVpbGRlcigpOwogICAgICAgICAgYnVpbGRlck1hcC5wdXQoa2V5LCBlbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmIChlbnRyeSBpbnN0YW5jZW9mIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkgewogICAgICAgICAgZW50cnkgPSAoKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkgZW50cnkpLnRvQnVpbGRlcigpOwogICAgICAgICAgYnVpbGRlck1hcC5wdXQoa2V5LCBlbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiAocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLkJ1aWxkZXIpIGVudHJ5OwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdEVudW1NYXBMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0RW51bU1hcExpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRLbm93bk1hcEZpZWxkQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zS25vd25NYXBGaWVsZCgKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0S25vd25NYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICBnZXRLbm93bk1hcEZpZWxkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgIGdldEtub3duTWFwRmllbGRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldEtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlICAgICAgICAgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldEtub3duTWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRVbmtub3duTWFwRmllbGRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc1Vua25vd25NYXBGaWVsZCgKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgIGdldFVua25vd25NYXBGaWVsZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgIGdldFVua25vd25NYXBGaWVsZE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlICAgICAgICAgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgZ2V0VW5rbm93bk1hcEZpZWxkT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RFbnVtTWFwTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKQogICAgICBUZXN0RW51bU1hcExpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RFbnVtTWFwTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0RW51bU1hcExpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0RW51bU1hcExpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdEVudW1NYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkUmVmbGVjdGlvbkFjY2Vzc29yIGludGVybmFsR2V0TWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgIGludCBudW1iZXIpIHsKICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICBjYXNlIDEwMToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKTsKICAgICAgICBjYXNlIDEwMjoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgfQogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlLmNsYXNzLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBLTk9XTl9NQVBfRklFTERfRklFTERfTlVNQkVSID0gMTAxOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgS25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkVOVU0sCiAgICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUuUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFLmdldE51bWJlcigpKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4ga25vd25NYXBGaWVsZF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkgewogICAgICBpZiAoa25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4ga25vd25NYXBGaWVsZF87CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4ga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyID0KICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyLm5ld0VudW1Db252ZXJ0ZXIoCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLmludGVybmFsR2V0VmFsdWVNYXAoKSwKICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUuUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFKTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICBpbnRlcm5hbEdldEFkYXB0ZWRLbm93bk1hcEZpZWxkTWFwKAogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXApIHsKICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSwgamF2YS5sYW5nLkludGVnZXI+KAogICAgICAgICAgICAgIG1hcCwga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyKTsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0S25vd25NYXBGaWVsZENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zS25vd25NYXBGaWVsZCgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0S25vd25NYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPgogICAgZ2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgcmV0dXJuIGdldEtub3duTWFwRmllbGRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgIGdldEtub3duTWFwRmllbGRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRLbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkpO30KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBnZXRLbm93bk1hcEZpZWxkT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgPyBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSkKICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldEtub3duTWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgVU5LTk9XTl9NQVBfRklFTERfRklFTERfTlVNQkVSID0gMTAyOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9Vbmtub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5FTlVNLAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLlBST1RPMl9NQVBfRU5VTV9GT09fTElURS5nZXROdW1iZXIoKSk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHVua25vd25NYXBGaWVsZF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKSB7CiAgICAgIGlmICh1bmtub3duTWFwRmllbGRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBVbmtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gdW5rbm93bk1hcEZpZWxkXzsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPiB1bmtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlciA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5uZXdFbnVtQ29udmVydGVyKAogICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZS5pbnRlcm5hbEdldFZhbHVlTWFwKCksCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLlBST1RPMl9NQVBfRU5VTV9GT09fTElURSk7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPgogICAgaW50ZXJuYWxHZXRBZGFwdGVkVW5rbm93bk1hcEZpZWxkTWFwKAogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXApIHsKICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSwgamF2YS5sYW5nLkludGVnZXI+KAogICAgICAgICAgICAgIG1hcCwgdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIpOwogICAgfQogICAgcHVibGljIGludCBnZXRVbmtub3duTWFwRmllbGRDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNVbmtub3duTWFwRmllbGQoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICBnZXRVbmtub3duTWFwRmllbGQoKSB7CiAgICAgIHJldHVybiBnZXRVbmtub3duTWFwRmllbGRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPgogICAgZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkVW5rbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKSk7fQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgZ2V0VW5rbm93bk1hcEZpZWxkT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpCiAgICAgICAgICAgICA/IHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldFVua25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKSwKICAgICAgICAgIEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTAxKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKSwKICAgICAgICAgIFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxMDIpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBrbm93bk1hcEZpZWxkX18gPSBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMDEsIGtub3duTWFwRmllbGRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIHVua25vd25NYXBGaWVsZF9fID0gVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMDIsIHVua25vd25NYXBGaWVsZF9fKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgb3RoZXIgPSAocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUpIG9iajsKCiAgICAgIGlmICghaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmICghaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgS05PV05fTUFQX0ZJRUxEX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBVTktOT1dOX01BUF9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvMl91bml0dGVzdC5UZXN0RW51bU1hcExpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKQogICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICAgIGludCBudW1iZXIpIHsKICAgICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgICAgY2FzZSAxMDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKTsKICAgICAgICAgIGNhc2UgMTAyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDEwMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKTsKICAgICAgICAgIGNhc2UgMTAyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlLmNsYXNzLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKS5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBidWlsZCgpIHsKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSByZXN1bHQgPSBuZXcgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5rbm93bk1hcEZpZWxkXyA9IGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpOwogICAgICAgICAgcmVzdWx0Lmtub3duTWFwRmllbGRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC51bmtub3duTWFwRmllbGRfID0gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKTsKICAgICAgICAgIHJlc3VsdC51bmtub3duTWFwRmllbGRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20ocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0S25vd25NYXBGaWVsZCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4MTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBieXRlcyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBrbm93bk1hcEZpZWxkX18gPSBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCkucGFyc2VGcm9tKGJ5dGVzKTsKICAgICAgICAgICAgICAgIGlmIChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLmZvck51bWJlcihrbm93bk1hcEZpZWxkX18uZ2V0VmFsdWUoKSkgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25MZW5ndGhEZWxpbWl0ZWRGaWVsZCgxMDEsIGJ5dGVzKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgICAga25vd25NYXBGaWVsZF9fLmdldEtleSgpLCBrbm93bk1hcEZpZWxkX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4MTAKICAgICAgICAgICAgICBjYXNlIDgxODogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJ5dGVzID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIHVua25vd25NYXBGaWVsZF9fID0gVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCkucGFyc2VGcm9tKGJ5dGVzKTsKICAgICAgICAgICAgICAgIGlmIChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLmZvck51bWJlcih1bmtub3duTWFwRmllbGRfXy5nZXRWYWx1ZSgpKSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93bkxlbmd0aERlbGltaXRlZEZpZWxkKDEwMiwgYnl0ZXMpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICAgIHVua25vd25NYXBGaWVsZF9fLmdldEtleSgpLCB1bmtub3duTWFwRmllbGRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgxOAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGtub3duTWFwRmllbGRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkgewogICAgICAgIGlmIChrbm93bk1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGtub3duTWFwRmllbGRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkgewogICAgICAgIGlmIChrbm93bk1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgICBrbm93bk1hcEZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgS25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIWtub3duTWFwRmllbGRfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBrbm93bk1hcEZpZWxkXyA9IGtub3duTWFwRmllbGRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldEtub3duTWFwRmllbGRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zS25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldEtub3duTWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPgogICAgICBnZXRLbm93bk1hcEZpZWxkKCkgewogICAgICAgIHJldHVybiBnZXRLbm93bk1hcEZpZWxkTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICAgIGdldEtub3duTWFwRmllbGRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZEtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpKTt9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldEtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgICA/IGtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKQogICAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBnZXRLbm93bk1hcEZpZWxkT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJLbm93bk1hcEZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVLbm93bk1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVLbm93bk1hcEZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkS25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRLbm93bk1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIGtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0JhY2t3YXJkKHZhbHVlKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxLbm93bk1hcEZpZWxkKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRBZGFwdGVkS25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKSkKICAgICAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdW5rbm93bk1hcEZpZWxkXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkgewogICAgICAgIGlmICh1bmtub3duTWFwRmllbGRfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB1bmtub3duTWFwRmllbGRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKSB7CiAgICAgICAgaWYgKHVua25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgICAgdW5rbm93bk1hcEZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghdW5rbm93bk1hcEZpZWxkXy5pc011dGFibGUoKSkgewogICAgICAgICAgdW5rbm93bk1hcEZpZWxkXyA9IHVua25vd25NYXBGaWVsZF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHVua25vd25NYXBGaWVsZF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRVbmtub3duTWFwRmllbGRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc1Vua25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgICAgZ2V0VW5rbm93bk1hcEZpZWxkKCkgewogICAgICAgIHJldHVybiBnZXRVbmtub3duTWFwRmllbGRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPgogICAgICBnZXRVbmtub3duTWFwRmllbGRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZFVua25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKSk7fQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldFVua25vd25NYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkKICAgICAgICAgICAgICAgPyB1bmtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKQogICAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldFVua25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB1bmtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclVua25vd25NYXBGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVVua25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVVbmtub3duTWFwRmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRVbmtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dFVua25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvQmFja3dhcmQodmFsdWUpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsVW5rbm93bk1hcEZpZWxkKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRBZGFwdGVkVW5rbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkpCiAgICAgICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0RW51bU1hcExpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0RW51bU1hcExpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0RW51bU1hcExpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdEVudW1NYXBMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdEVudW1NYXBMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVudW1NYXBMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbnVtTWFwTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldEtub3duTWFwRmllbGRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNLbm93bk1hcEZpZWxkKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRLbm93bk1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgIGdldEtub3duTWFwRmllbGQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0S25vd25NYXBGaWVsZE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZ2V0S25vd25NYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgICAgICAgICBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZ2V0S25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFVua25vd25NYXBGaWVsZENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zVW5rbm93bk1hcEZpZWxkKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRVbmtub3duTWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0VW5rbm93bk1hcEZpZWxkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGdldFVua25vd25NYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgICAgICAgICBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUpCiAgICAgIFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgaW50IG51bWJlcikgewogICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgIGNhc2UgMTAxOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpOwogICAgICAgIGNhc2UgMTAyOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICB9CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUuY2xhc3MsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEtOT1dOX01BUF9GSUVMRF9GSUVMRF9OVU1CRVIgPSAxMDE7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9Lbm93bk1hcEZpZWxkRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRU5VTSwKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZS5FX1BST1RPMl9NQVBfRU5VTV9GT09fTElURS5nZXROdW1iZXIoKSk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGtub3duTWFwRmllbGRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgaWYgKGtub3duTWFwRmllbGRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIGtub3duTWFwRmllbGRfOwogICAgfQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5Db252ZXJ0ZXI8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+IGtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlciA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5uZXdFbnVtQ29udmVydGVyKAogICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZS5pbnRlcm5hbEdldFZhbHVlTWFwKCksCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlLkVfUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFKTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICBpbnRlcm5hbEdldEFkYXB0ZWRLbm93bk1hcEZpZWxkTWFwKAogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXApIHsKICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSwgamF2YS5sYW5nLkludGVnZXI+KAogICAgICAgICAgICAgIG1hcCwga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyKTsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0S25vd25NYXBGaWVsZENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zS25vd25NYXBGaWVsZCgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0S25vd25NYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgcmV0dXJuIGdldEtub3duTWFwRmllbGRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgIGdldEtub3duTWFwRmllbGRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRLbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkpO30KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRLbm93bk1hcEZpZWxkT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgPyBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSkKICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGdldEtub3duTWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgVU5LTk9XTl9NQVBfRklFTERfRklFTERfTlVNQkVSID0gMTAyOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9Vbmtub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5FTlVNLAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlLkVfUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFLmdldE51bWJlcigpKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdW5rbm93bk1hcEZpZWxkXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpIHsKICAgICAgaWYgKHVua25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiB1bmtub3duTWFwRmllbGRfOwogICAgfQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5Db252ZXJ0ZXI8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+IHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyID0KICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyLm5ld0VudW1Db252ZXJ0ZXIoCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlLmludGVybmFsR2V0VmFsdWVNYXAoKSwKICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUuRV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUpOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgIGludGVybmFsR2V0QWRhcHRlZFVua25vd25NYXBGaWVsZE1hcCgKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwKSB7CiAgICAgIHJldHVybiBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUsIGphdmEubGFuZy5JbnRlZ2VyPigKICAgICAgICAgICAgICBtYXAsIHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyKTsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0VW5rbm93bk1hcEZpZWxkQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zVW5rbm93bk1hcEZpZWxkKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldFVua25vd25NYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0VW5rbm93bk1hcEZpZWxkKCkgewogICAgICByZXR1cm4gZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgIGdldFVua25vd25NYXBGaWVsZE1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZFVua25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkpO30KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGdldFVua25vd25NYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgPyB1bmtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKQogICAgICAgICAgICAgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCksCiAgICAgICAgICBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEwMSk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCksCiAgICAgICAgICBVbmtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTAyKTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAga25vd25NYXBGaWVsZF9fID0gS25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTAxLCBrbm93bk1hcEZpZWxkX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICB1bmtub3duTWFwRmllbGRfXyA9IFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTAyLCB1bmtub3duTWFwRmllbGRfXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIG90aGVyID0gKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKSBvYmo7CgogICAgICBpZiAoIWludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0S25vd25NYXBGaWVsZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoIWludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEtOT1dOX01BUF9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgVU5LTk9XTl9NQVBfRklFTERfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSkKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgMTAxOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICBjYXNlIDEwMjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICAgIH0KICAgICAgfQogICAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InJhd3R5cGVzIn0pCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkUmVmbGVjdGlvbkFjY2Vzc29yIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICAgIGludCBudW1iZXIpIHsKICAgICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgICAgY2FzZSAxMDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICBjYXNlIDEwMjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5jbGFzcywgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgYnVpbGQoKSB7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcmVzdWx0ID0gbmV3IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQua25vd25NYXBGaWVsZF8gPSBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKTsKICAgICAgICAgIHJlc3VsdC5rbm93bk1hcEZpZWxkXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQudW5rbm93bk1hcEZpZWxkXyA9IGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICByZXN1bHQudW5rbm93bk1hcEZpZWxkXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldEtub3duTWFwRmllbGQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgODEwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnl0ZXMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAga25vd25NYXBGaWVsZF9fID0gS25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLnBhcnNlRnJvbShieXRlcyk7CiAgICAgICAgICAgICAgICBpZiAocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZS5mb3JOdW1iZXIoa25vd25NYXBGaWVsZF9fLmdldFZhbHVlKCkpID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duTGVuZ3RoRGVsaW1pdGVkRmllbGQoMTAxLCBieXRlcyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICAgIGtub3duTWFwRmllbGRfXy5nZXRLZXkoKSwga25vd25NYXBGaWVsZF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODEwCiAgICAgICAgICAgICAgY2FzZSA4MTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBieXRlcyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICB1bmtub3duTWFwRmllbGRfXyA9IFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLnBhcnNlRnJvbShieXRlcyk7CiAgICAgICAgICAgICAgICBpZiAocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZS5mb3JOdW1iZXIodW5rbm93bk1hcEZpZWxkX18uZ2V0VmFsdWUoKSkgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25MZW5ndGhEZWxpbWl0ZWRGaWVsZCgxMDIsIGJ5dGVzKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgICB1bmtub3duTWFwRmllbGRfXy5nZXRLZXkoKSwgdW5rbm93bk1hcEZpZWxkX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4MTgKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBrbm93bk1hcEZpZWxkXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgICBpZiAoa25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpIHsKICAgICAgICBpZiAoa25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgICAga25vd25NYXBGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFrbm93bk1hcEZpZWxkXy5pc011dGFibGUoKSkgewogICAgICAgICAga25vd25NYXBGaWVsZF8gPSBrbm93bk1hcEZpZWxkXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4ga25vd25NYXBGaWVsZF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRLbm93bk1hcEZpZWxkQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc0tub3duTWFwRmllbGQoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRLbm93bk1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgICAgZ2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgICByZXR1cm4gZ2V0S25vd25NYXBGaWVsZE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgICBnZXRLbm93bk1hcEZpZWxkTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRLbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKSk7fQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRLbm93bk1hcEZpZWxkT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkKICAgICAgICAgICAgICAgPyBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSkKICAgICAgICAgICAgICAgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZ2V0S25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4ga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyS25vd25NYXBGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlS25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICAgICAgICBnZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZEtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0S25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9CYWNrd2FyZCh2YWx1ZSkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsS25vd25NYXBGaWVsZCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0QWRhcHRlZEtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkpCiAgICAgICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHVua25vd25NYXBGaWVsZF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpIHsKICAgICAgICBpZiAodW5rbm93bk1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdW5rbm93bk1hcEZpZWxkXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkgewogICAgICAgIGlmICh1bmtub3duTWFwRmllbGRfID09IG51bGwpIHsKICAgICAgICAgIHVua25vd25NYXBGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIXVua25vd25NYXBGaWVsZF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIHVua25vd25NYXBGaWVsZF8gPSB1bmtub3duTWFwRmllbGRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB1bmtub3duTWFwRmllbGRfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0VW5rbm93bk1hcEZpZWxkQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNVbmtub3duTWFwRmllbGQoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldFVua25vd25NYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICAgIGdldFVua25vd25NYXBGaWVsZCgpIHsKICAgICAgICByZXR1cm4gZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgICAgZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRVbmtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkpO30KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpCiAgICAgICAgICAgICAgID8gdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSkKICAgICAgICAgICAgICAgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJVbmtub3duTWFwRmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVVbmtub3duTWFwRmllbGQoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICAgICAgICBnZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkVW5rbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRVbmtub3duTWFwRmllbGQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB1bmtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0JhY2t3YXJkKHZhbHVlKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbFVua25vd25NYXBGaWVsZCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0QWRhcHRlZFVua25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpKQogICAgICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdE1lc3NhZ2VNYXBMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvMl91bml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMyTWVzc2FnZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJNZXNzYWdlKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPgogICAgZ2V0TWFwSW50MzJNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPgogICAgZ2V0TWFwSW50MzJNZXNzYWdlTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE1hcEludDMyTWVzc2FnZU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0TWFwSW50MzJNZXNzYWdlT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RNZXNzYWdlTWFwTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKQogICAgICBUZXN0TWVzc2FnZU1hcExpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RNZXNzYWdlTWFwTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0TWVzc2FnZU1hcExpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0TWVzc2FnZU1hcExpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdE1lc3NhZ2VNYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkUmVmbGVjdGlvbkFjY2Vzc29yIGludGVybmFsR2V0TWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgIGludCBudW1iZXIpIHsKICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKTsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgIH0KICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZS5jbGFzcywgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX01FU1NBR0VfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX01hcEludDMyTWVzc2FnZUVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLk1FU1NBR0UsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IG1hcEludDMyTWVzc2FnZV87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+CiAgICBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpIHsKICAgICAgaWYgKG1hcEludDMyTWVzc2FnZV8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDMyTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMk1lc3NhZ2VfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMk1lc3NhZ2VDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMk1lc3NhZ2UoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJNZXNzYWdlTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldE1hcEludDMyTWVzc2FnZSgpIHsKICAgICAgcmV0dXJuIGdldE1hcEludDMyTWVzc2FnZU1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldE1hcEludDMyTWVzc2FnZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRNYXBJbnQzMk1lc3NhZ2VPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE1hcEludDMyTWVzc2FnZU9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpLAogICAgICAgICAgTWFwSW50MzJNZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4KICAgICAgICBtYXBJbnQzMk1lc3NhZ2VfXyA9IE1hcEludDMyTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMSwgbWFwSW50MzJNZXNzYWdlX18pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSBvdGhlciA9IChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQzMl9NRVNTQUdFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUpCiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InJhd3R5cGVzIn0pCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkUmVmbGVjdGlvbkFjY2Vzc29yIGludGVybmFsR2V0TWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyTWVzc2FnZSgpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZS5jbGFzcywgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgYnVpbGQoKSB7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcmVzdWx0ID0gbmV3IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJNZXNzYWdlXyA9IGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuYnVpbGQoTWFwSW50MzJNZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDEwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPgogICAgICAgICAgICAgICAgbWFwSW50MzJNZXNzYWdlX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBJbnQzMk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMk1lc3NhZ2VfXy5nZXRLZXkoKSwgbWFwSW50MzJNZXNzYWdlX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTAKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJNZXNzYWdlQ29udmVydGVyIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXIuQ29udmVydGVyPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiB7CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGJ1aWxkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgdmFsKSB7CiAgICAgICAgICBpZiAodmFsIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgeyByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIHZhbDsgfQogICAgICAgICAgcmV0dXJuICgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyKSB2YWwpLmJ1aWxkKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGRlZmF1bHRFbnRyeSgpIHsKICAgICAgICAgIHJldHVybiBNYXBJbnQzMk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5OwogICAgICAgIH0KICAgICAgfTsKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgTWFwSW50MzJNZXNzYWdlQ29udmVydGVyIG1hcEludDMyTWVzc2FnZUNvbnZlcnRlciA9IG5ldyBNYXBJbnQzMk1lc3NhZ2VDb252ZXJ0ZXIoKTsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyPiBtYXBJbnQzMk1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpIHsKICAgICAgICBpZiAobWFwSW50MzJNZXNzYWdlXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPD4obWFwSW50MzJNZXNzYWdlQ29udmVydGVyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyTWVzc2FnZV87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkgewogICAgICAgIGlmIChtYXBJbnQzMk1lc3NhZ2VfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMyTWVzc2FnZV8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8PihtYXBJbnQzMk1lc3NhZ2VDb252ZXJ0ZXIpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDMyTWVzc2FnZV87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMk1lc3NhZ2VDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMk1lc3NhZ2UoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRNYXBJbnQzMk1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEludDMyTWVzc2FnZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldE1hcEludDMyTWVzc2FnZU1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5nZXRJbW11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE1hcEludDMyTWVzc2FnZU9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiBtYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwSW50MzJNZXNzYWdlQ29udmVydGVyLmJ1aWxkKG1hcC5nZXQoa2V5KSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRNYXBJbnQzMk1lc3NhZ2VPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiBtYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyTWVzc2FnZUNvbnZlcnRlci5idWlsZChtYXAuZ2V0KGtleSkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwSW50MzJNZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEludDMyTWVzc2FnZSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5lbnN1cmVNZXNzYWdlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJNZXNzYWdlKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKCiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAgdmFsdWUiKTsgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG8yX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQzMk1lc3NhZ2UoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiB2YWx1ZXMpIHsKICAgICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGUgOiB2YWx1ZXMuZW50cnlTZXQoKSkgewogICAgICAgICAgaWYgKGUuZ2V0S2V5KCkgPT0gbnVsbCB8fCBlLmdldFZhbHVlKCkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBwdXRNYXBJbnQzMk1lc3NhZ2VCdWlsZGVySWZBYnNlbnQoCiAgICAgICAgICBpbnQga2V5KSB7CiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gYnVpbGRlck1hcCA9IGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGVudHJ5ID0gYnVpbGRlck1hcC5nZXQoa2V5KTsKICAgICAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICAgICAgZW50cnkgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLm5ld0J1aWxkZXIoKTsKICAgICAgICAgIGJ1aWxkZXJNYXAucHV0KGtleSwgZW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoZW50cnkgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSB7CiAgICAgICAgICBlbnRyeSA9ICgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgZW50cnkpLnRvQnVpbGRlcigpOwogICAgICAgICAgYnVpbGRlck1hcC5wdXQoa2V5LCBlbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyKSBlbnRyeTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90bzJfdW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE1lc3NhZ2VNYXBMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RNZXNzYWdlTWFwTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RNZXNzYWdlTWFwTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RNZXNzYWdlTWFwTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWVzc2FnZU1hcExpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdFJlcXVpcmVkTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGEgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzQSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBhID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBpbnQgZ2V0QSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYiA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBiIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNCKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGIgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGIuCiAgICAgKi8KICAgIGludCBnZXRCKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBjID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0MoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYyA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYy4KICAgICAqLwogICAgaW50IGdldEMoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0UmVxdWlyZWRMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlKQogICAgICBUZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0UmVxdWlyZWRMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RSZXF1aXJlZExpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0UmVxdWlyZWRMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RSZXF1aXJlZExpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UmVxdWlyZWRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLmNsYXNzLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEFfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgaW50IGFfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzQSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBhID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgIHJldHVybiBhXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBCX0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIGludCBiXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGIgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0IoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYiA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRCKCkgewogICAgICByZXR1cm4gYl87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgQ19GSUVMRF9OVU1CRVIgPSAzOwogICAgcHJpdmF0ZSBpbnQgY18gPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBjID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNDKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGMgPSAzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0QygpIHsKICAgICAgcmV0dXJuIGNfOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmICghaGFzQSgpKSB7CiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFoYXNCKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWhhc0MoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMSwgYV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDIsIGJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigzLCBjXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMSwgYV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMiwgYl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMywgY18pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIG90aGVyID0gKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc0EoKSAhPSBvdGhlci5oYXNBKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0EoKSkgewogICAgICAgIGlmIChnZXRBKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0QSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0IoKSAhPSBvdGhlci5oYXNCKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0IoKSkgewogICAgICAgIGlmIChnZXRCKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0QigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0MoKSAhPSBvdGhlci5oYXNDKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0MoKSkgewogICAgICAgIGlmIChnZXRDKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0QygpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoaGFzQSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgQV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0QSgpOwogICAgICB9CiAgICAgIGlmIChoYXNCKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBCX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRCKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0MoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIENfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEMoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLmNsYXNzLCBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGFfID0gMDsKICAgICAgICBiXyA9IDA7CiAgICAgICAgY18gPSAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgYnVpbGQoKSB7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcmVzdWx0ID0gbmV3IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuYV8gPSBhXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5iXyA9IGJfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmNfID0gY187CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzQSgpKSB7CiAgICAgICAgICBzZXRBKG90aGVyLmdldEEoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNCKCkpIHsKICAgICAgICAgIHNldEIob3RoZXIuZ2V0QigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0MoKSkgewogICAgICAgICAgc2V0QyhvdGhlci5nZXRDKCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFoYXNBKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFoYXNCKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFoYXNDKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIGFfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGNhc2UgMTY6IHsKICAgICAgICAgICAgICAgIGJfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYKICAgICAgICAgICAgICBjYXNlIDI0OiB7CiAgICAgICAgICAgICAgICBjXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI0CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IGFfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGEgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzQSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGEgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRBKCkgewogICAgICAgIHJldHVybiBhXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYSA9IDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGEgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRBKGludCB2YWx1ZSkgewoKICAgICAgICBhXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYSA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckEoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGFfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgYl8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYiA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNCKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYiA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBiLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEIoKSB7CiAgICAgICAgcmV0dXJuIGJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBiID0gMjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEIoaW50IHZhbHVlKSB7CgogICAgICAgIGJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBiID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgYl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBjXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBjID0gMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0MoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBjID0gMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0QygpIHsKICAgICAgICByZXR1cm4gY187CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGMgPSAzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBjIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0QyhpbnQgdmFsdWUpIHsKCiAgICAgICAgY18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGMgPSAzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJDKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICBjXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdFJlcXVpcmVkTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0UmVxdWlyZWRMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdFJlcXVpcmVkTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RSZXF1aXJlZExpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdFJlcXVpcmVkTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFNJTkdMRV9GSUVMRF9OVU1CRVIgPSAxMDAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5leHRlbmQgLnByb3RvMl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IHNpbmdsZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgICAubmV3TWVzc2FnZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSwKICAgICAgICAgIDAsCiAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuY2xhc3MsCiAgICAgICAgICBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIH0KCiAgcHVibGljIGludGVyZmFjZSBGb3JlaWduTWVzc2FnZUFyZW5hTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0MoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYy4KICAgICAqLwogICAgaW50IGdldEMoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKQogICAgICBGb3JlaWduTWVzc2FnZUFyZW5hTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBGb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBGb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuY2xhc3MsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IENfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgaW50IGNfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBjIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzQygpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEMoKSB7CiAgICAgIHJldHVybiBjXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGNfKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBjXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBvdGhlciA9IChwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKSBvYmo7CgogICAgICBpZiAoaGFzQygpICE9IG90aGVyLmhhc0MoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzQygpKSB7CiAgICAgICAgaWYgKGdldEMoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRDKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNDKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBDX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRDKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUpCiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuY2xhc3MsIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBjXyA9IDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgYnVpbGQoKSB7CiAgICAgICAgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcmVzdWx0ID0gbmV3IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5jXyA9IGNfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgocHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IHByb3RvMl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNDKCkpIHsKICAgICAgICAgIHNldEMob3RoZXIuZ2V0QygpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICBjXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBpbnQgY18gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNDKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEMoKSB7CiAgICAgICAgcmV0dXJuIGNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEMoaW50IHZhbHVlKSB7CgogICAgICAgIGNfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQygpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgY18gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvMl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgcHJvdG8yX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8Rm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8Rm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBGb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPEZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPEZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90bzJfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMySW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFVpbnQzMlVpbnQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFVpbnQ2NFVpbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQzMlNpbnQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ludDY0U2ludDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQ2NFNpbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkNjRGaXhlZDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkNjRGaXhlZDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJGbG9hdEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZsb2F0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwQm9vbEJvb2xFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwQm9vbEJvb2xFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFN0cmluZ1N0cmluZ0VudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTdHJpbmdTdHJpbmdFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJCeXRlc0VudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJFbnVtRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJGb3JlaWduTWVzc2FnZUVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9UZWJvcmluZ0VudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9UZWJvcmluZ0VudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJJbnQzMkVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMySW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFVpbnQ2NFVpbnQ2NEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFVpbnQ2NFVpbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50MzJTaW50MzJFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50MzJTaW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDY0U2ludDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDY0U2ludDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEZpeGVkMzJGaXhlZDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkZsb2F0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJGbG9hdEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRG91YmxlRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEJvb2xCb29sRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwQm9vbEJvb2xFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkJ5dGVzRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJGb3JlaWduTWVzc2FnZUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfTWFwRmllbGRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX0tub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX0tub3duTWFwRmllbGRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9Vbmtub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX1Vua25vd25NYXBGaWVsZEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfS25vd25NYXBGaWVsZEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX1Vua25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9NYXBJbnQzMk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX01hcEludDMyTWVzc2FnZUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CgogIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgcmV0dXJuIGRlc2NyaXB0b3I7CiAgfQogIHByaXZhdGUgc3RhdGljICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIGRlc2NyaXB0b3I7CiAgc3RhdGljIHsKICAgIGphdmEubGFuZy5TdHJpbmdbXSBkZXNjcmlwdG9yRGF0YSA9IHsKICAgICAgIlxuXCdnb29nbGUvcHJvdG9idWYvbWFwX2xpdGVfdW5pdHRlc3QucHJvdCIgKwogICAgICAib1wwMjJcMDE3cHJvdG8yX3VuaXR0ZXN0XDAzMiNnb29nbGUvcHJvdG9idWYvdW5pdCIgKwogICAgICAidGVzdF9saXRlLnByb3RvXCJcMjU3XDAyM1xuXDAxM1Rlc3RNYXBMaXRlXDAyMkhcblwwMTdtYXBfaSIgKwogICAgICAibnQzMl9pbnQzMlwwMzBcMDAxIFwwMDMoXDAxMzIvLnByb3RvMl91bml0dGVzdC5UZXN0TSIgKwogICAgICAiYXBMaXRlLk1hcEludDMySW50MzJFbnRyeVwwMjJIXG5cMDE3bWFwX2ludDY0X2kiICsKICAgICAgIm50NjRcMDMwXDAwMiBcMDAzKFwwMTMyLy5wcm90bzJfdW5pdHRlc3QuVGVzdE1hcExpdGUiICsKICAgICAgIi5NYXBJbnQ2NEludDY0RW50cnlcMDIyTFxuXDAyMW1hcF91aW50MzJfdWludDMyIiArCiAgICAgICJcMDMwXDAwMyBcMDAzKFwwMTMyMS5wcm90bzJfdW5pdHRlc3QuVGVzdE1hcExpdGUuTWFwIiArCiAgICAgICJVaW50MzJVaW50MzJFbnRyeVwwMjJMXG5cMDIxbWFwX3VpbnQ2NF91aW50NjRcMDMwXDAwNCIgKwogICAgICAiIFwwMDMoXDAxMzIxLnByb3RvMl91bml0dGVzdC5UZXN0TWFwTGl0ZS5NYXBVaSIgKwogICAgICAibnQ2NFVpbnQ2NEVudHJ5XDAyMkxcblwwMjFtYXBfc2ludDMyX3NpbnQzMlwwMzBcMDA1IFwwMDMiICsKICAgICAgIihcMDEzMjEucHJvdG8yX3VuaXR0ZXN0LlRlc3RNYXBMaXRlLk1hcFNpbnQiICsKICAgICAgIjMyU2ludDMyRW50cnlcMDIyTFxuXDAyMW1hcF9zaW50NjRfc2ludDY0XDAzMFwwMDYgXDAwMyhcMDEzIiArCiAgICAgICIyMS5wcm90bzJfdW5pdHRlc3QuVGVzdE1hcExpdGUuTWFwU2ludDY0IiArCiAgICAgICJTaW50NjRFbnRyeVwwMjJQXG5cMDIzbWFwX2ZpeGVkMzJfZml4ZWQzMlwwMzBcMDA3IFwwMDMoXDAxMyIgKwogICAgICAiMjMucHJvdG8yX3VuaXR0ZXN0LlRlc3RNYXBMaXRlLk1hcEZpeGVkMyIgKwogICAgICAiMkZpeGVkMzJFbnRyeVwwMjJQXG5cMDIzbWFwX2ZpeGVkNjRfZml4ZWQ2NFwwMzBcMDEwIFwwMDMiICsKICAgICAgIihcMDEzMjMucHJvdG8yX3VuaXR0ZXN0LlRlc3RNYXBMaXRlLk1hcEZpeGUiICsKICAgICAgImQ2NEZpeGVkNjRFbnRyeVwwMjJUXG5cMDI1bWFwX3NmaXhlZDMyX3NmaXhlZDMyIiArCiAgICAgICJcMDMwXHQgXDAwMyhcMDEzMjUucHJvdG8yX3VuaXR0ZXN0LlRlc3RNYXBMaXRlLk1hcCIgKwogICAgICAiU2ZpeGVkMzJTZml4ZWQzMkVudHJ5XDAyMlRcblwwMjVtYXBfc2ZpeGVkNjRfc2YiICsKICAgICAgIml4ZWQ2NFwwMzBcbiBcMDAzKFwwMTMyNS5wcm90bzJfdW5pdHRlc3QuVGVzdE1hcExpIiArCiAgICAgICJ0ZS5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlcMDIySFxuXDAxN21hcF9pbnQzMiIgKwogICAgICAiX2Zsb2F0XDAzMFwwMTMgXDAwMyhcMDEzMi8ucHJvdG8yX3VuaXR0ZXN0LlRlc3RNYXBMaSIgKwogICAgICAidGUuTWFwSW50MzJGbG9hdEVudHJ5XDAyMkpcblwwMjBtYXBfaW50MzJfZG91YmwiICsKICAgICAgImVcMDMwXDAxNCBcMDAzKFwwMTMyMC5wcm90bzJfdW5pdHRlc3QuVGVzdE1hcExpdGUuTWEiICsKICAgICAgInBJbnQzMkRvdWJsZUVudHJ5XDAyMkRcblxybWFwX2Jvb2xfYm9vbFwwMzBcciBcMDAzKFwwMTMiICsKICAgICAgIjItLnByb3RvMl91bml0dGVzdC5UZXN0TWFwTGl0ZS5NYXBCb29sQm8iICsKICAgICAgIm9sRW50cnlcMDIyTFxuXDAyMW1hcF9zdHJpbmdfc3RyaW5nXDAzMFwwMTYgXDAwMyhcMDEzMjEucHJvIiArCiAgICAgICJ0bzJfdW5pdHRlc3QuVGVzdE1hcExpdGUuTWFwU3RyaW5nU3RyaW5nIiArCiAgICAgICJFbnRyeVwwMjJIXG5cMDE3bWFwX2ludDMyX2J5dGVzXDAzMFwwMTcgXDAwMyhcMDEzMi8ucHJvdG8yXyIgKwogICAgICAidW5pdHRlc3QuVGVzdE1hcExpdGUuTWFwSW50MzJCeXRlc0VudHJ5XDAyMiIgKwogICAgICAiRlxuXDAxNm1hcF9pbnQzMl9lbnVtXDAzMFwwMjAgXDAwMyhcMDEzMi4ucHJvdG8yX3VuaXR0ZXMiICsKICAgICAgInQuVGVzdE1hcExpdGUuTWFwSW50MzJFbnVtRW50cnlcMDIyW1xuXDAzMW1hcF9pIiArCiAgICAgICJudDMyX2ZvcmVpZ25fbWVzc2FnZVwwMzBcMDIxIFwwMDMoXDAxMzI4LnByb3RvMl91bml0IiArCiAgICAgICJ0ZXN0LlRlc3RNYXBMaXRlLk1hcEludDMyRm9yZWlnbk1lc3NhZ2VFIiArCiAgICAgICJudHJ5XDAyMjxcblwwMTB0ZWJvcmluZ1wwMzBcMDIyIFwwMDMoXDAxMzIqLnByb3RvMl91bml0dGVzdCIgKwogICAgICAiLlRlc3RNYXBMaXRlLlRlYm9yaW5nRW50cnlcMDMyNFxuXDAyMk1hcEludDMySW4iICsKICAgICAgInQzMkVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAwNTpcMDAyOFwwMDEiICsKICAgICAgIlwwMzI0XG5cMDIyTWFwSW50NjRJbnQ2NEVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDNcMDIyXHJcblwwMDV2IiArCiAgICAgICJhbHVlXDAzMFwwMDIgXDAwMShcMDAzOlwwMDI4XDAwMVwwMzI2XG5cMDI0TWFwVWludDMyVWludDMyRW50cnlcMDIyXDAxMyIgKwogICAgICAiXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcclwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShccjpcMDAyOFwwMDFcMDMyNlxuXDAyNE1hcFVpbiIgKwogICAgICAidDY0VWludDY0RW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNFwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMSIgKwogICAgICAiKFwwMDQ6XDAwMjhcMDAxXDAzMjZcblwwMjRNYXBTaW50MzJTaW50MzJFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgIiArCiAgICAgICJcMDAxKFwwMjFcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAyMTpcMDAyOFwwMDFcMDMyNlxuXDAyNE1hcFNpbnQ2NFNpbnQ2IiArCiAgICAgICI0RW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAyMlwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDIyOlwwMDI4XDAwMVwwMzI4IiArCiAgICAgICJcblwwMjZNYXBGaXhlZDMyRml4ZWQzMkVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDdcMDIyXHJcbiIgKwogICAgICAiXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDA3OlwwMDI4XDAwMVwwMzI4XG5cMDI2TWFwRml4ZWQ2NEZpeGVkNjRFbnQiICsKICAgICAgInJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDZcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAwNjpcMDAyOFwwMDFcMDMyOlxuXDAzME1hIiArCiAgICAgICJwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMTdcMDIyXHJcblwwMDV2IiArCiAgICAgICJhbHVlXDAzMFwwMDIgXDAwMShcMDE3OlwwMDI4XDAwMVwwMzI6XG5cMDMwTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudCIgKwogICAgICAicnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAyMFwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDIwOlwwMDI4XDAwMVwwMzI0XG5cMDIyTWEiICsKICAgICAgInBJbnQzMkZsb2F0RW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNVwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIiICsKICAgICAgIiBcMDAxKFwwMDI6XDAwMjhcMDAxXDAzMjVcblwwMjNNYXBJbnQzMkRvdWJsZUVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSIgKwogICAgICAiIFwwMDEoXDAwNVwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDAxOlwwMDI4XDAwMVwwMzIyXG5cMDIwTWFwQm9vbEJvb2xFbiIgKwogICAgICAidHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMTBcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAxMDpcMDAyOFwwMDFcMDMyNlxuXDAyNE0iICsKICAgICAgImFwU3RyaW5nU3RyaW5nRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXHRcMDIyXHJcblwwMDV2YWx1IiArCiAgICAgICJlXDAzMFwwMDIgXDAwMShcdDpcMDAyOFwwMDFcMDMyNFxuXDAyMk1hcEludDMyQnl0ZXNFbnRyeVwwMjJcMDEzXG5cMDAza2V5IiArCiAgICAgICJcMDMwXDAwMSBcMDAxKFwwMDVcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAxNDpcMDAyOFwwMDFcMDMyUVxuXDAyMU1hcEludDMyRW51IiArCiAgICAgICJtRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNVwwMjIrXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMTYyXDAzNC5wcm8iICsKICAgICAgInRvMl91bml0dGVzdC5NYXBFbnVtTGl0ZTpcMDAyOFwwMDFcMDMyYlxuXDAzM01hcEludDMyIiArCiAgICAgICJGb3JlaWduTWVzc2FnZUVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyMlxuXDAwNXZhbHUiICsKICAgICAgImVcMDMwXDAwMiBcMDAxKFwwMTMyIy5wcm90bzJfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2UiICsKICAgICAgIkxpdGU6XDAwMjhcMDAxXDAzMi9cblxyVGVib3JpbmdFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMlxyIiArCiAgICAgICJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAwNTpcMDAyOFwwMDFcIlwyMzdcMDIzXG5cMDIwVGVzdEFyZW5hTWFwTGl0ZVwwMjJNIiArCiAgICAgICJcblwwMTdtYXBfaW50MzJfaW50MzJcMDMwXDAwMSBcMDAzKFwwMTMyNC5wcm90bzJfdW5pdHRlcyIgKwogICAgICAidC5UZXN0QXJlbmFNYXBMaXRlLk1hcEludDMySW50MzJFbnRyeVwwMjJNXG4iICsKICAgICAgIlwwMTdtYXBfaW50NjRfaW50NjRcMDMwXDAwMiBcMDAzKFwwMTMyNC5wcm90bzJfdW5pdHRlc3QiICsKICAgICAgIi5UZXN0QXJlbmFNYXBMaXRlLk1hcEludDY0SW50NjRFbnRyeVwwMjJRXG5cMDIxIiArCiAgICAgICJtYXBfdWludDMyX3VpbnQzMlwwMzBcMDAzIFwwMDMoXDAxMzI2LnByb3RvMl91bml0dGVzIiArCiAgICAgICJ0LlRlc3RBcmVuYU1hcExpdGUuTWFwVWludDMyVWludDMyRW50cnlcMDIyIiArCiAgICAgICJRXG5cMDIxbWFwX3VpbnQ2NF91aW50NjRcMDMwXDAwNCBcMDAzKFwwMTMyNi5wcm90bzJfdW5pdCIgKwogICAgICAidGVzdC5UZXN0QXJlbmFNYXBMaXRlLk1hcFVpbnQ2NFVpbnQ2NEVudCIgKwogICAgICAicnlcMDIyUVxuXDAyMW1hcF9zaW50MzJfc2ludDMyXDAzMFwwMDUgXDAwMyhcMDEzMjYucHJvdG8yX3UiICsKICAgICAgIm5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZS5NYXBTaW50MzJTaW50MzIiICsKICAgICAgIkVudHJ5XDAyMlFcblwwMjFtYXBfc2ludDY0X3NpbnQ2NFwwMzBcMDA2IFwwMDMoXDAxMzI2LnByb3RvIiArCiAgICAgICIyX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwU2ludDY0U2luIiArCiAgICAgICJ0NjRFbnRyeVwwMjJVXG5cMDIzbWFwX2ZpeGVkMzJfZml4ZWQzMlwwMzBcMDA3IFwwMDMoXDAxMzI4LiIgKwogICAgICAicHJvdG8yX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwRml4ZSIgKwogICAgICAiZDMyRml4ZWQzMkVudHJ5XDAyMlVcblwwMjNtYXBfZml4ZWQ2NF9maXhlZDY0XDAzMFwwMTAiICsKICAgICAgIiBcMDAzKFwwMTMyOC5wcm90bzJfdW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZS4iICsKICAgICAgIk1hcEZpeGVkNjRGaXhlZDY0RW50cnlcMDIyWVxuXDAyNW1hcF9zZml4ZWQzMl9zIiArCiAgICAgICJmaXhlZDMyXDAzMFx0IFwwMDMoXDAxMzI6LnByb3RvMl91bml0dGVzdC5UZXN0QXJlbiIgKwogICAgICAiYU1hcExpdGUuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5XDAyMllcblwwMjVtYXAiICsKICAgICAgIl9zZml4ZWQ2NF9zZml4ZWQ2NFwwMzBcbiBcMDAzKFwwMTMyOi5wcm90bzJfdW5pdHRlIiArCiAgICAgICJzdC5UZXN0QXJlbmFNYXBMaXRlLk1hcFNmaXhlZDY0U2ZpeGVkNjRFIiArCiAgICAgICJudHJ5XDAyMk1cblwwMTdtYXBfaW50MzJfZmxvYXRcMDMwXDAxMyBcMDAzKFwwMTMyNC5wcm90bzJfdSIgKwogICAgICAibml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLk1hcEludDMyRmxvYXRFbiIgKwogICAgICAidHJ5XDAyMk9cblwwMjBtYXBfaW50MzJfZG91YmxlXDAzMFwwMTQgXDAwMyhcMDEzMjUucHJvdG8yX3UiICsKICAgICAgIm5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZS5NYXBJbnQzMkRvdWJsZUUiICsKICAgICAgIm50cnlcMDIySVxuXHJtYXBfYm9vbF9ib29sXDAzMFxyIFwwMDMoXDAxMzIyLnByb3RvMl91bmkiICsKICAgICAgInR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwQm9vbEJvb2xFbnRyeVwwMjIiICsKICAgICAgIlFcblwwMjFtYXBfc3RyaW5nX3N0cmluZ1wwMzBcMDE2IFwwMDMoXDAxMzI2LnByb3RvMl91bml0IiArCiAgICAgICJ0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwU3RyaW5nU3RyaW5nRW50IiArCiAgICAgICJyeVwwMjJNXG5cMDE3bWFwX2ludDMyX2J5dGVzXDAzMFwwMTcgXDAwMyhcMDEzMjQucHJvdG8yX3VuaSIgKwogICAgICAidHRlc3QuVGVzdEFyZW5hTWFwTGl0ZS5NYXBJbnQzMkJ5dGVzRW50ciIgKwogICAgICAieVwwMjJLXG5cMDE2bWFwX2ludDMyX2VudW1cMDMwXDAyMCBcMDAzKFwwMTMyMy5wcm90bzJfdW5pdHQiICsKICAgICAgImVzdC5UZXN0QXJlbmFNYXBMaXRlLk1hcEludDMyRW51bUVudHJ5XDAyMmAiICsKICAgICAgIlxuXDAzMW1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2VcMDMwXDAyMSBcMDAzKFwwMTMyPS5wcm90IiArCiAgICAgICJvMl91bml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLk1hcEludDMyRm9yIiArCiAgICAgICJlaWduTWVzc2FnZUVudHJ5XDAzMjRcblwwMjJNYXBJbnQzMkludDMyRW50cnlcMDIyXDAxMyIgKwogICAgICAiXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDU6XDAwMjhcMDAxXDAzMjRcblwwMjJNYXBJbnQiICsKICAgICAgIjY0SW50NjRFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDAzXDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDMiICsKICAgICAgIjpcMDAyOFwwMDFcMDMyNlxuXDAyNE1hcFVpbnQzMlVpbnQzMkVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKCIgKwogICAgICAiXHJcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXHI6XDAwMjhcMDAxXDAzMjZcblwwMjRNYXBVaW50NjRVaW50NjRFIiArCiAgICAgICJudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDRcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAwNDpcMDAyOFwwMDFcMDMyNlxuXDAyNCIgKwogICAgICAiTWFwU2ludDMyU2ludDMyRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAyMVwwMjJcclxuXDAwNXZhbCIgKwogICAgICAidWVcMDMwXDAwMiBcMDAxKFwwMjE6XDAwMjhcMDAxXDAzMjZcblwwMjRNYXBTaW50NjRTaW50NjRFbnRyeVwwMjJcMDEzXG5cMDAzIiArCiAgICAgICJrZXlcMDMwXDAwMSBcMDAxKFwwMjJcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAyMjpcMDAyOFwwMDFcMDMyOFxuXDAyNk1hcEZpeGVkIiArCiAgICAgICIzMkZpeGVkMzJFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA3XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxIiArCiAgICAgICIoXDAwNzpcMDAyOFwwMDFcMDMyOFxuXDAyNk1hcEZpeGVkNjRGaXhlZDY0RW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzAiICsKICAgICAgIlwwMDEgXDAwMShcMDA2XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDY6XDAwMjhcMDAxXDAzMjpcblwwMzBNYXBTZml4ZWQzMlMiICsKICAgICAgImZpeGVkMzJFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDE3XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMTciICsKICAgICAgIjpcMDAyOFwwMDFcMDMyOlxuXDAzME1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMCIgKwogICAgICAiXDAwMSBcMDAxKFwwMjBcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAyMDpcMDAyOFwwMDFcMDMyNFxuXDAyMk1hcEludDMyRmxvYSIgKwogICAgICAidEVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAwMjpcMDAyOFwwMDFcMDMyNSIgKwogICAgICAiXG5cMDIzTWFwSW50MzJEb3VibGVFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMlxyXG5cMDA1dmEiICsKICAgICAgImx1ZVwwMzBcMDAyIFwwMDEoXDAwMTpcMDAyOFwwMDFcMDMyMlxuXDAyME1hcEJvb2xCb29sRW50cnlcMDIyXDAxM1xuXDAwM2tleSIgKwogICAgICAiXDAzMFwwMDEgXDAwMShcMDEwXDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMTA6XDAwMjhcMDAxXDAzMjZcblwwMjRNYXBTdHJpbmdTdCIgKwogICAgICAicmluZ0VudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFx0XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFx0OlwwMDI4IiArCiAgICAgICJcMDAxXDAzMjRcblwwMjJNYXBJbnQzMkJ5dGVzRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNVwwMjJcclxuXDAwNSIgKwogICAgICAidmFsdWVcMDMwXDAwMiBcMDAxKFwwMTQ6XDAwMjhcMDAxXDAzMlFcblwwMjFNYXBJbnQzMkVudW1FbnRyeVwwMjJcMDEzXG5cMDAzIiArCiAgICAgICJrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyK1xuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDE2MlwwMzQucHJvdG8yX3VuaXR0ZSIgKwogICAgICAic3QuTWFwRW51bUxpdGU6XDAwMjhcMDAxXDAzMmdcblwwMzNNYXBJbnQzMkZvcmVpZ25NZXMiICsKICAgICAgInNhZ2VFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMjdcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAxMzIoLiIgKwogICAgICAicHJvdG8yX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlOiIgKwogICAgICAiXDAwMjhcMDAxXCJcMjc2XDAwMVxuXDAzMlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlXDAyMkxcblx0bWEiICsKICAgICAgInBfZmllbGRcMDMwXDAwMSBcMDAzKFwwMTMyOS5wcm90bzJfdW5pdHRlc3QuVGVzdFJlcXUiICsKICAgICAgImlyZWRNZXNzYWdlTWFwTGl0ZS5NYXBGaWVsZEVudHJ5XDAzMlJcblxyTWFwRiIgKwogICAgICAiaWVsZEVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyMFxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDEzMiEuIiArCiAgICAgICJwcm90bzJfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZTpcMDAyOFwwMDFcIlwzNDdcMDAyXG4iICsKICAgICAgIlwwMTdUZXN0RW51bU1hcExpdGVcMDIyTFxuXDAxN2tub3duX21hcF9maWVsZFwwMzBlIFwwMDMoIiArCiAgICAgICJcMDEzMjMucHJvdG8yX3VuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZS5Lbm93IiArCiAgICAgICJuTWFwRmllbGRFbnRyeVwwMjJQXG5cMDIxdW5rbm93bl9tYXBfZmllbGRcMDMwZiBcMDAzKCIgKwogICAgICAiXDAxMzI1LnByb3RvMl91bml0dGVzdC5UZXN0RW51bU1hcExpdGUuVW5rbiIgKwogICAgICAib3duTWFwRmllbGRFbnRyeVwwMzJYXG5cMDIyS25vd25NYXBGaWVsZEVudHJ5XDAyMlwwMTMiICsKICAgICAgIlxuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNVwwMjIxXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMTYyXCIucHJvdG8yX3VuaXQiICsKICAgICAgInRlc3QuUHJvdG8yTWFwRW51bUxpdGU6XDAwMjhcMDAxXDAzMlpcblwwMjRVbmtub3duTWFwIiArCiAgICAgICJGaWVsZEVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyMVxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDE2MlwiIiArCiAgICAgICIucHJvdG8yX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlOlwwMDI4XDAwMVwiXDIyNCIgKwogICAgICAiXDAwM1xuXDAzMFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZVwwMjJVXG5cMDE3a25vd25fbWFwIiArCiAgICAgICJfZmllbGRcMDMwZSBcMDAzKFwwMTMyPC5wcm90bzJfdW5pdHRlc3QuVGVzdEVudW1NIiArCiAgICAgICJhcFBsdXNFeHRyYUxpdGUuS25vd25NYXBGaWVsZEVudHJ5XDAyMllcblwwMjF1biIgKwogICAgICAia25vd25fbWFwX2ZpZWxkXDAzMGYgXDAwMyhcMDEzMj4ucHJvdG8yX3VuaXR0ZXN0LiIgKwogICAgICAiVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlLlVua25vd25NYXBGaWVsZCIgKwogICAgICAiRW50cnlcMDMyYVxuXDAyMktub3duTWFwRmllbGRFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1IiArCiAgICAgICJcMDIyOlxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDE2MisucHJvdG8yX3VuaXR0ZXN0LlByb3RvMiIgKwogICAgICAiTWFwRW51bVBsdXNFeHRyYUxpdGU6XDAwMjhcMDAxXDAzMmNcblwwMjRVbmtub3duTWFwRmkiICsKICAgICAgImVsZEVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyOlxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDE2MisucCIgKwogICAgICAicm90bzJfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdCIgKwogICAgICAiZTpcMDAyOFwwMDFcIlwzMDRcMDAxXG5cMDIyVGVzdE1lc3NhZ2VNYXBMaXRlXDAyMlNcblwwMjFtYXBfaW50MyIgKwogICAgICAiMl9tZXNzYWdlXDAzMFwwMDEgXDAwMyhcMDEzMjgucHJvdG8yX3VuaXR0ZXN0LlRlc3RNZSIgKwogICAgICAic3NhZ2VNYXBMaXRlLk1hcEludDMyTWVzc2FnZUVudHJ5XDAzMllcblwwMjRNYXAiICsKICAgICAgIkludDMyTWVzc2FnZUVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyMFxuXDAwNXZhbHVlXDAzMCIgKwogICAgICAiXDAwMiBcMDAxKFwwMTMyIS5wcm90bzJfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSIgKwogICAgICAiOlwwMDI4XDAwMVwiXDIxN1wwMDFcblwwMjBUZXN0UmVxdWlyZWRMaXRlXDAyMlx0XG5cMDAxYVwwMzBcMDAxIFwwMDIoXDAwNVwwMjJcdFxuXDAwMSIgKwogICAgICAiYlwwMzBcMDAyIFwwMDIoXDAwNVwwMjJcdFxuXDAwMWNcMDMwXDAwMyBcMDAyKFwwMDUyWlxuXDAwNnNpbmdsZVwwMjImLnByb3RvMl91biIgKwogICAgICAiaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMzUwXDAwNyBcMDAxKFwwMTMyIS5wciIgKwogICAgICAib3RvMl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlXCIkXG5cMDI3Rm9yZWlnIiArCiAgICAgICJuTWVzc2FnZUFyZW5hTGl0ZVwwMjJcdFxuXDAwMWNcMDMwXDAwMSBcMDAxKFwwMDUqbVxuXDAyMVByb3RvMk1hIiArCiAgICAgICJwRW51bUxpdGVcMDIyXDAzNFxuXDAzMFBST1RPMl9NQVBfRU5VTV9GT09fTElURVwwMjBcMDAwXDAyMiIgKwogICAgICAiXDAzNFxuXDAzMFBST1RPMl9NQVBfRU5VTV9CQVJfTElURVwwMjBcMDAxXDAyMlwwMzRcblwwMzBQUk9UTzJfIiArCiAgICAgICJNQVBfRU5VTV9CQVpfTElURVwwMjBcMDAyKlwyMzZcMDAxXG5cMDMyUHJvdG8yTWFwRW51bVBsdSIgKwogICAgICAic0V4dHJhTGl0ZVwwMjJcMDM2XG5cMDMyRV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUiICsKICAgICAgIlwwMjBcMDAwXDAyMlwwMzZcblwwMzJFX1BST1RPMl9NQVBfRU5VTV9CQVJfTElURVwwMjBcMDAxXDAyMlwwMzZcblwwMzJFXyIgKwogICAgICAiUFJPVE8yX01BUF9FTlVNX0JBWl9MSVRFXDAyMFwwMDJcMDIyIFxuXDAzNEVfUFJPVE8yX00iICsKICAgICAgIkFQX0VOVU1fRVhUUkFfTElURVwwMjBcMDAzKlJcblwwMTNNYXBFbnVtTGl0ZVwwMjJcMDI1XG5cMDIxTSIgKwogICAgICAiQVBfRU5VTV9GT09fTElURVwwMjBcMDAwXDAyMlwwMjVcblwwMjFNQVBfRU5VTV9CQVJfTElURVwwMjAiICsKICAgICAgIlwwMDFcMDIyXDAyNVxuXDAyMU1BUF9FTlVNX0JBWl9MSVRFXDAyMFwwMDJCXDAwNUhcMDAzXDM3MFwwMDFcMDAxIgogICAgfTsKICAgIGRlc2NyaXB0b3IgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIC5pbnRlcm5hbEJ1aWxkR2VuZXJhdGVkRmlsZUZyb20oZGVzY3JpcHRvckRhdGEsCiAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3JbXSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5nZXREZXNjcmlwdG9yKCksCiAgICAgICAgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIk1hcEludDMySW50MzIiLCAiTWFwSW50NjRJbnQ2NCIsICJNYXBVaW50MzJVaW50MzIiLCAiTWFwVWludDY0VWludDY0IiwgIk1hcFNpbnQzMlNpbnQzMiIsICJNYXBTaW50NjRTaW50NjQiLCAiTWFwRml4ZWQzMkZpeGVkMzIiLCAiTWFwRml4ZWQ2NEZpeGVkNjQiLCAiTWFwU2ZpeGVkMzJTZml4ZWQzMiIsICJNYXBTZml4ZWQ2NFNmaXhlZDY0IiwgIk1hcEludDMyRmxvYXQiLCAiTWFwSW50MzJEb3VibGUiLCAiTWFwQm9vbEJvb2wiLCAiTWFwU3RyaW5nU3RyaW5nIiwgIk1hcEludDMyQnl0ZXMiLCAiTWFwSW50MzJFbnVtIiwgIk1hcEludDMyRm9yZWlnbk1lc3NhZ2UiLCAiVGVib3JpbmciLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJJbnQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMySW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJJbnQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgyKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFVpbnQzMlVpbnQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgzKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFVpbnQ2NFVpbnQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg0KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQzMlNpbnQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ludDY0U2ludDY0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg1KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ludDY0U2ludDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQ2NFNpbnQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDYpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDcpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoOCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoOSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJGbG9hdEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZsb2F0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRG91YmxlRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRG91YmxlRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRG91YmxlRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTIpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxMyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFN0cmluZ1N0cmluZ0VudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTdHJpbmdTdHJpbmdFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDE0KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJCeXRlc0VudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkJ5dGVzRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkVudW1FbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDE1KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJFbnVtRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJGb3JlaWduTWVzc2FnZUVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTYpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX1RlYm9yaW5nRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxNyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX1RlYm9yaW5nRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX1RlYm9yaW5nRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDEpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJNYXBJbnQzMkludDMyIiwgIk1hcEludDY0SW50NjQiLCAiTWFwVWludDMyVWludDMyIiwgIk1hcFVpbnQ2NFVpbnQ2NCIsICJNYXBTaW50MzJTaW50MzIiLCAiTWFwU2ludDY0U2ludDY0IiwgIk1hcEZpeGVkMzJGaXhlZDMyIiwgIk1hcEZpeGVkNjRGaXhlZDY0IiwgIk1hcFNmaXhlZDMyU2ZpeGVkMzIiLCAiTWFwU2ZpeGVkNjRTZml4ZWQ2NCIsICJNYXBJbnQzMkZsb2F0IiwgIk1hcEludDMyRG91YmxlIiwgIk1hcEJvb2xCb29sIiwgIk1hcFN0cmluZ1N0cmluZyIsICJNYXBJbnQzMkJ5dGVzIiwgIk1hcEludDMyRW51bSIsICJNYXBJbnQzMkZvcmVpZ25NZXNzYWdlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJJbnQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJJbnQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQ2NEludDY0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDEpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQ2NEludDY0RW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFVpbnQzMlVpbnQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgyKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBVaW50MzJVaW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBVaW50MzJVaW50MzJFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDMpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFVpbnQ2NFVpbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFVpbnQ2NFVpbnQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50MzJTaW50MzJFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoNCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNpbnQ2NFNpbnQ2NEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg1KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50NjRTaW50NjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50NjRTaW50NjRFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoNik7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg3KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEZpeGVkNjRGaXhlZDY0RW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoOCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg5KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkZsb2F0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDEwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkZsb2F0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJGbG9hdEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJEb3VibGVFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxMik7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwQm9vbEJvb2xFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTdHJpbmdTdHJpbmdFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTMpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFN0cmluZ1N0cmluZ0VudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFN0cmluZ1N0cmluZ0VudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkJ5dGVzRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDE0KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkJ5dGVzRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJCeXRlc0VudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkVudW1FbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTUpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDE2KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJGb3JlaWduTWVzc2FnZUVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMik7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiTWFwRmllbGQiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZV9NYXBGaWVsZEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZV9NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDMpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS25vd25NYXBGaWVsZCIsICJVbmtub3duTWFwRmllbGQiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX0tub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX0tub3duTWFwRmllbGRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX0tub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9Vbmtub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX1Vua25vd25NYXBGaWVsZEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoNCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLbm93bk1hcEZpZWxkIiwgIlVua25vd25NYXBGaWVsZCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfS25vd25NYXBGaWVsZEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX1Vua25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDEpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9Vbmtub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg1KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIk1hcEludDMyTWVzc2FnZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfTWFwSW50MzJNZXNzYWdlRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9NYXBJbnQzMk1lc3NhZ2VFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX01hcEludDMyTWVzc2FnZUVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg2KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiQSIsICJCIiwgIkMiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90bzJfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoNyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG8yX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvMl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiQyIsIH0pOwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZ2V0RGVzY3JpcHRvcigpOwogIH0KCiAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG91dGVyX2NsYXNzX3Njb3BlKQp9ClBLAQIKAAoAAAAAAAAAIQAmbx6fMgAAADIAAAAUAAAAAAAAAAAAAAAAAAAAAABNRVRBLUlORi9NQU5JRkVTVC5NRlBLAQIKAAoAAAAAAAAAIQA5LqJKylwAAMpcAAArAAAAAAAAAAAAAAAAAGQAAABjb20vZ29vZ2xlL3Byb3RvYnVmL1VuaXR0ZXN0SW1wb3J0TGl0ZS5qYXZhUEsBAgoACgAAAAAAAAAhAOFJJdf0UQAA9FEAADEAAAAAAAAAAAAAAAAAd10AAGNvbS9nb29nbGUvcHJvdG9idWYvVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLmphdmFQSwECCgAKAAAAAAAAACEAhKMEGT6kGgA+pBoAJQAAAAAAAAAAAAAAAAC6rwAAY29tL2dvb2dsZS9wcm90b2J1Zi9Vbml0dGVzdExpdGUuamF2YVBLAQIKAAoAAAAAAAAAIQDgxnWGSPUJAEj1CQAkAAAAAAAAAAAAAAAAADtUGwBwcm90bzJfdW5pdHRlc3QvTWFwTGl0ZVVuaXR0ZXN0LmphdmFQSwUGAAAAAAUABQCfAQAAxUklAAAA