UEsDBAoAAAAAAAAAIQAmbx6fMgAAADIAAAAUAAAATUVUQS1JTkYvTUFOSUZFU1QuTUZNYW5pZmVzdC1WZXJzaW9uOiAxLjAKQ3JlYXRlZC1CeTogMS42LjAgKHByb3RvYykKClBLAwQKAAAAAAAAACEAXW6LNs5cAADOXAAAKwAAAGNvbS9nb29nbGUvcHJvdG9idWYvVW5pdHRlc3RJbXBvcnRMaXRlLmphdmEvLyBHZW5lcmF0ZWQgYnkgdGhlIHByb3RvY29sIGJ1ZmZlciBjb21waWxlci4gIERPIE5PVCBFRElUIQovLyBzb3VyY2U6IGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9pbXBvcnRfbGl0ZS5wcm90bwoKLy8gUHJvdG9idWYgSmF2YSBWZXJzaW9uOiAzLjI1LjQtZGV2CnBhY2thZ2UgY29tLmdvb2dsZS5wcm90b2J1ZjsKCnB1YmxpYyBmaW5hbCBjbGFzcyBVbml0dGVzdEltcG9ydExpdGUgewogIHByaXZhdGUgVW5pdHRlc3RJbXBvcnRMaXRlKCkge30KICBwdWJsaWMgc3RhdGljIHZvaWQgcmVnaXN0ZXJBbGxFeHRlbnNpb25zKAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSByZWdpc3RyeSkgewogIH0KCiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeSByZWdpc3RyeSkgewogICAgcmVnaXN0ZXJBbGxFeHRlbnNpb25zKAogICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSkgcmVnaXN0cnkpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiBlbnVtIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGV9CiAgICovCiAgcHVibGljIGVudW0gSW1wb3J0RW51bUxpdGUKICAgICAgaW1wbGVtZW50cyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sTWVzc2FnZUVudW0gewogICAgLyoqCiAgICAgKiA8Y29kZT5JTVBPUlRfTElURV9GT08gPSA3OzwvY29kZT4KICAgICAqLwogICAgSU1QT1JUX0xJVEVfRk9PKDcpLAogICAgLyoqCiAgICAgKiA8Y29kZT5JTVBPUlRfTElURV9CQVIgPSA4OzwvY29kZT4KICAgICAqLwogICAgSU1QT1JUX0xJVEVfQkFSKDgpLAogICAgLyoqCiAgICAgKiA8Y29kZT5JTVBPUlRfTElURV9CQVogPSA5OzwvY29kZT4KICAgICAqLwogICAgSU1QT1JUX0xJVEVfQkFaKDkpLAogICAgOwoKICAgIC8qKgogICAgICogPGNvZGU+SU1QT1JUX0xJVEVfRk9PID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IElNUE9SVF9MSVRFX0ZPT19WQUxVRSA9IDc7CiAgICAvKioKICAgICAqIDxjb2RlPklNUE9SVF9MSVRFX0JBUiA9IDg7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBJTVBPUlRfTElURV9CQVJfVkFMVUUgPSA4OwogICAgLyoqCiAgICAgKiA8Y29kZT5JTVBPUlRfTElURV9CQVogPSA5OzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgSU1QT1JUX0xJVEVfQkFaX1ZBTFVFID0gOTsKCgogICAgcHVibGljIGZpbmFsIGludCBnZXROdW1iZXIoKSB7CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjZm9yTnVtYmVyKGludCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIHN0YXRpYyBJbXBvcnRFbnVtTGl0ZSB2YWx1ZU9mKGludCB2YWx1ZSkgewogICAgICByZXR1cm4gZm9yTnVtYmVyKHZhbHVlKTsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIEltcG9ydEVudW1MaXRlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgIGNhc2UgNzogcmV0dXJuIElNUE9SVF9MSVRFX0ZPTzsKICAgICAgICBjYXNlIDg6IHJldHVybiBJTVBPUlRfTElURV9CQVI7CiAgICAgICAgY2FzZSA5OiByZXR1cm4gSU1QT1JUX0xJVEVfQkFaOwogICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPEltcG9ydEVudW1MaXRlPgogICAgICAgIGludGVybmFsR2V0VmFsdWVNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbFZhbHVlTWFwOwogICAgfQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDwKICAgICAgICBJbXBvcnRFbnVtTGl0ZT4gaW50ZXJuYWxWYWx1ZU1hcCA9CiAgICAgICAgICBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxJbXBvcnRFbnVtTGl0ZT4oKSB7CiAgICAgICAgICAgIHB1YmxpYyBJbXBvcnRFbnVtTGl0ZSBmaW5kVmFsdWVCeU51bWJlcihpbnQgbnVtYmVyKSB7CiAgICAgICAgICAgICAgcmV0dXJuIEltcG9ydEVudW1MaXRlLmZvck51bWJlcihudW1iZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IKICAgICAgICBnZXRWYWx1ZURlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCkuZ2V0VmFsdWVzKCkuZ2V0KG9yZGluYWwoKSk7CiAgICB9CiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMCk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgSW1wb3J0RW51bUxpdGVbXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICBwdWJsaWMgc3RhdGljIEltcG9ydEVudW1MaXRlIHZhbHVlT2YoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yIGRlc2MpIHsKICAgICAgaWYgKGRlc2MuZ2V0VHlwZSgpICE9IGdldERlc2NyaXB0b3IoKSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKAogICAgICAgICAgIkVudW1WYWx1ZURlc2NyaXB0b3IgaXMgbm90IGZvciB0aGlzIHR5cGUuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIFZBTFVFU1tkZXNjLmdldEluZGV4KCldOwogICAgfQoKICAgIHByaXZhdGUgZmluYWwgaW50IHZhbHVlOwoKICAgIHByaXZhdGUgSW1wb3J0RW51bUxpdGUoaW50IHZhbHVlKSB7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUpCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIEltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGQgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkLgogICAgICovCiAgICBpbnQgZ2V0RCgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBJbXBvcnRNZXNzYWdlTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUpCiAgICAgIEltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBJbXBvcnRNZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBJbXBvcnRNZXNzYWdlTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIEltcG9ydE1lc3NhZ2VMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IEltcG9ydE1lc3NhZ2VMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9JbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfSW1wb3J0TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgaW50IGRfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZCA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEQoKSB7CiAgICAgIHJldHVybiBkXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGRfKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBkXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlKSBvYmo7CgogICAgICBpZiAoaGFzRCgpICE9IG90aGVyLmhhc0QoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRCgpKSB7CiAgICAgICAgaWYgKGdldEQoKQogICAgICAgICAgICAhPSBvdGhlci5nZXREKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNEKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBEX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfSW1wb3J0TWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9JbXBvcnRNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgZF8gPSAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X0ltcG9ydE1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZF8gPSBkXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKG90aGVyLmhhc0QoKSkgewogICAgICAgICAgc2V0RChvdGhlci5nZXREKCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIGRfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGludCBkXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0QoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RCgpIHsKICAgICAgICByZXR1cm4gZF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGQgPSAxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RChpbnQgdmFsdWUpIHsKCiAgICAgICAgZF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBkXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxJbXBvcnRNZXNzYWdlTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxJbXBvcnRNZXNzYWdlTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8SW1wb3J0TWVzc2FnZUxpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8SW1wb3J0TWVzc2FnZUxpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9JbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfSW1wb3J0TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwoKICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3IKICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgIHJldHVybiBkZXNjcmlwdG9yOwogIH0KICBwcml2YXRlIHN0YXRpYyAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICBkZXNjcmlwdG9yOwogIHN0YXRpYyB7CiAgICBqYXZhLmxhbmcuU3RyaW5nW10gZGVzY3JpcHRvckRhdGEgPSB7CiAgICAgICJcbipnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X2xpdGUucCIgKwogICAgICAicm90b1wwMjJcMDMwcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0XDAzMjFnb29nbGUvcCIgKwogICAgICAicm90b2J1Zi91bml0dGVzdF9pbXBvcnRfcHVibGljX2xpdGUucHJvdCIgKwogICAgICAib1wiXDAzNlxuXDAyMUltcG9ydE1lc3NhZ2VMaXRlXDAyMlx0XG5cMDAxZFwwMzBcMDAxIFwwMDEoXDAwNSpPXG5cMDE2SW1wIiArCiAgICAgICJvcnRFbnVtTGl0ZVwwMjJcMDIzXG5cMDE3SU1QT1JUX0xJVEVfRk9PXDAyMFwwMDdcMDIyXDAyM1xuXDAxN0lNUE8iICsKICAgICAgIlJUX0xJVEVfQkFSXDAyMFwwMTBcMDIyXDAyM1xuXDAxN0lNUE9SVF9MSVRFX0JBWlwwMjBcdEJcMDI3XG5cMDIzY28iICsKICAgICAgIm0uZ29vZ2xlLnByb3RvYnVmSFwwMDNQXDAwMCIKICAgIH07CiAgICBkZXNjcmlwdG9yID0gY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICAuaW50ZXJuYWxCdWlsZEdlbmVyYXRlZEZpbGVGcm9tKGRlc2NyaXB0b3JEYXRhLAogICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yW10gewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuZ2V0RGVzY3JpcHRvcigpLAogICAgICAgIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9JbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfSW1wb3J0TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X0ltcG9ydE1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJEIiwgfSk7CiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5nZXREZXNjcmlwdG9yKCk7CiAgfQoKICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQob3V0ZXJfY2xhc3Nfc2NvcGUpCn0KUEsDBAoAAAAAAAAAIQAj9DSJ+FEAAPhRAAAxAAAAY29tL2dvb2dsZS9wcm90b2J1Zi9Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuamF2YS8vIEdlbmVyYXRlZCBieSB0aGUgcHJvdG9jb2wgYnVmZmVyIGNvbXBpbGVyLiAgRE8gTk9UIEVESVQhCi8vIHNvdXJjZTogZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2ltcG9ydF9wdWJsaWNfbGl0ZS5wcm90bwoKLy8gUHJvdG9idWYgSmF2YSBWZXJzaW9uOiAzLjI1LjQtZGV2CnBhY2thZ2UgY29tLmdvb2dsZS5wcm90b2J1ZjsKCnB1YmxpYyBmaW5hbCBjbGFzcyBVbml0dGVzdEltcG9ydFB1YmxpY0xpdGUgewogIHByaXZhdGUgVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlKCkge30KICBwdWJsaWMgc3RhdGljIHZvaWQgcmVnaXN0ZXJBbGxFeHRlbnNpb25zKAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSByZWdpc3RyeSkgewogIH0KCiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeSByZWdpc3RyeSkgewogICAgcmVnaXN0ZXJBbGxFeHRlbnNpb25zKAogICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSkgcmVnaXN0cnkpOwogIH0KICBwdWJsaWMgaW50ZXJmYWNlIFB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGUgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBlID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBlLgogICAgICovCiAgICBpbnQgZ2V0RSgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUpCiAgICAgIFB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfUHVibGljSW1wb3J0TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEVfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgaW50IGVfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBlID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEUoKSB7CiAgICAgIHJldHVybiBlXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGVfKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBlXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKSBvYmo7CgogICAgICBpZiAoaGFzRSgpICE9IG90aGVyLmhhc0UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRSgpKSB7CiAgICAgICAgaWYgKGdldEUoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRFKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNFKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRFKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfUHVibGljSW1wb3J0TWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgZV8gPSAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X1B1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZV8gPSBlXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKG90aGVyLmhhc0UoKSkgewogICAgICAgICAgc2V0RShvdGhlci5nZXRFKCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIGVfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGludCBlXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBlID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBlID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGUuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RSgpIHsKICAgICAgICByZXR1cm4gZV87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGUgPSAxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBlIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RShpbnQgdmFsdWUpIHsKCiAgICAgICAgZV8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGUgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJFKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBlXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxQdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UHVibGljSW1wb3J0TWVzc2FnZUxpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UHVibGljSW1wb3J0TWVzc2FnZUxpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfUHVibGljSW1wb3J0TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwoKICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3IKICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgIHJldHVybiBkZXNjcmlwdG9yOwogIH0KICBwcml2YXRlIHN0YXRpYyAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICBkZXNjcmlwdG9yOwogIHN0YXRpYyB7CiAgICBqYXZhLmxhbmcuU3RyaW5nW10gZGVzY3JpcHRvckRhdGEgPSB7CiAgICAgICJcbjFnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpYyIgKwogICAgICAiX2xpdGUucHJvdG9cMDIyXDAzMHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydFwiJFxuIiArCiAgICAgICJcMDI3UHVibGljSW1wb3J0TWVzc2FnZUxpdGVcMDIyXHRcblwwMDFlXDAzMFwwMDEgXDAwMShcMDA1QlwwMjdcblwwMjNjIiArCiAgICAgICJvbS5nb29nbGUucHJvdG9idWZIXDAwMyIKICAgIH07CiAgICBkZXNjcmlwdG9yID0gY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICAuaW50ZXJuYWxCdWlsZEdlbmVyYXRlZEZpbGVGcm9tKGRlc2NyaXB0b3JEYXRhLAogICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yW10gewogICAgICAgIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfUHVibGljSW1wb3J0TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X1B1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJFIiwgfSk7CiAgfQoKICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQob3V0ZXJfY2xhc3Nfc2NvcGUpCn0KUEsDBAoAAAAAAAAAIQBKzoNSuLAaALiwGgAlAAAAY29tL2dvb2dsZS9wcm90b2J1Zi9Vbml0dGVzdExpdGUuamF2YS8vIEdlbmVyYXRlZCBieSB0aGUgcHJvdG9jb2wgYnVmZmVyIGNvbXBpbGVyLiAgRE8gTk9UIEVESVQhCi8vIHNvdXJjZTogZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG8KCi8vIFByb3RvYnVmIEphdmEgVmVyc2lvbjogMy4yNS40LWRldgpwYWNrYWdlIGNvbS5nb29nbGUucHJvdG9idWY7CgpwdWJsaWMgZmluYWwgY2xhc3MgVW5pdHRlc3RMaXRlIHsKICBwcml2YXRlIFVuaXR0ZXN0TGl0ZSgpIHt9CiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgcmVnaXN0cnkpIHsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEludDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxJbnQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsVWludDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxVaW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbFNpbnQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsU2ludDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxGaXhlZDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxGaXhlZDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxTZml4ZWQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsU2ZpeGVkNjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEZsb2F0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxEb3VibGVFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEJvb2xFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbFN0cmluZ0V4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsQnl0ZXNFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEdyb3VwRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxOZXN0ZWRNZXNzYWdlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxGb3JlaWduTWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsSW1wb3J0TWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsTmVzdGVkRW51bUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsRm9yZWlnbkVudW1FeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbEltcG9ydEVudW1FeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vcHRpb25hbFN0cmluZ1BpZWNlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxDb3JkRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub3B0aW9uYWxMYXp5TWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRJbnQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkSW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZFVpbnQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkVWludDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRTaW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZFNpbnQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkRml4ZWQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkRml4ZWQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkU2ZpeGVkMzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRGbG9hdEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkRG91YmxlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRCb29sRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRTdHJpbmdFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZEJ5dGVzRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRHcm91cEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkTmVzdGVkTWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZEltcG9ydE1lc3NhZ2VFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZE5lc3RlZEVudW1FeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5yZXBlYXRlZEZvcmVpZ25FbnVtRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRJbXBvcnRFbnVtRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucmVwZWF0ZWRTdHJpbmdQaWVjZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkQ29yZEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnJlcGVhdGVkTGF6eU1lc3NhZ2VFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0SW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0SW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0VWludDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZGVmYXVsdFVpbnQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRTaW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0U2ludDY0RXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZGVmYXVsdEZpeGVkMzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0Rml4ZWQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRTZml4ZWQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRTZml4ZWQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRGbG9hdEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHREb3VibGVFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0Qm9vbEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRTdHJpbmdFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0Qnl0ZXNFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5kZWZhdWx0TmVzdGVkRW51bUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRGb3JlaWduRW51bUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmRlZmF1bHRJbXBvcnRFbnVtRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZGVmYXVsdFN0cmluZ1BpZWNlRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZGVmYXVsdENvcmRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5vbmVvZlVpbnQzMkV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9uZW9mTmVzdGVkTWVzc2FnZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLm9uZW9mU3RyaW5nRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUub25lb2ZCeXRlc0V4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnBhY2tlZEludDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucGFja2VkSW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRVaW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRVaW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRTaW50MzJFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRTaW50NjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRGaXhlZDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucGFja2VkRml4ZWQ2NEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnBhY2tlZFNmaXhlZDMyRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUucGFja2VkU2ZpeGVkNjRFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRGbG9hdEV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnBhY2tlZERvdWJsZUV4dGVuc2lvbkxpdGUpOwogICAgcmVnaXN0cnkuYWRkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLnBhY2tlZEJvb2xFeHRlbnNpb25MaXRlKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5wYWNrZWRFbnVtRXh0ZW5zaW9uTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUudGVzdEFsbFR5cGVzTGl0ZSk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUubmVzdGVkRXh0ZW5zaW9uKTsKICAgIHJlZ2lzdHJ5LmFkZChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5vcHRpb25hbEV4dCk7CiAgICByZWdpc3RyeS5hZGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUucmVwZWF0ZWRFeHQpOwogIH0KCiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeSByZWdpc3RyeSkgewogICAgcmVnaXN0ZXJBbGxFeHRlbnNpb25zKAogICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSkgcmVnaXN0cnkpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiBlbnVtIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGV9CiAgICovCiAgcHVibGljIGVudW0gRm9yZWlnbkVudW1MaXRlCiAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Qcm90b2NvbE1lc3NhZ2VFbnVtIHsKICAgIC8qKgogICAgICogPGNvZGU+Rk9SRUlHTl9MSVRFX0ZPTyA9IDQ7PC9jb2RlPgogICAgICovCiAgICBGT1JFSUdOX0xJVEVfRk9PKDQpLAogICAgLyoqCiAgICAgKiA8Y29kZT5GT1JFSUdOX0xJVEVfQkFaID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIEZPUkVJR05fTElURV9CQVooNiksCiAgICAvKioKICAgICAqIDxjb2RlPkZPUkVJR05fTElURV9CQVIgPSA1OzwvY29kZT4KICAgICAqLwogICAgRk9SRUlHTl9MSVRFX0JBUig1KSwKICAgIDsKCiAgICAvKioKICAgICAqIDxjb2RlPkZPUkVJR05fTElURV9GT08gPSA0OzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRk9SRUlHTl9MSVRFX0ZPT19WQUxVRSA9IDQ7CiAgICAvKioKICAgICAqIDxjb2RlPkZPUkVJR05fTElURV9CQVogPSA2OzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRk9SRUlHTl9MSVRFX0JBWl9WQUxVRSA9IDY7CiAgICAvKioKICAgICAqIDxjb2RlPkZPUkVJR05fTElURV9CQVIgPSA1OzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRk9SRUlHTl9MSVRFX0JBUl9WQUxVRSA9IDU7CgoKICAgIHB1YmxpYyBmaW5hbCBpbnQgZ2V0TnVtYmVyKCkgewogICAgICByZXR1cm4gdmFsdWU7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgI2Zvck51bWJlcihpbnQpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBzdGF0aWMgRm9yZWlnbkVudW1MaXRlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgIHJldHVybiBmb3JOdW1iZXIodmFsdWUpOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgRm9yZWlnbkVudW1MaXRlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgIGNhc2UgNDogcmV0dXJuIEZPUkVJR05fTElURV9GT087CiAgICAgICAgY2FzZSA2OiByZXR1cm4gRk9SRUlHTl9MSVRFX0JBWjsKICAgICAgICBjYXNlIDU6IHJldHVybiBGT1JFSUdOX0xJVEVfQkFSOwogICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPEZvcmVpZ25FbnVtTGl0ZT4KICAgICAgICBpbnRlcm5hbEdldFZhbHVlTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxWYWx1ZU1hcDsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8CiAgICAgICAgRm9yZWlnbkVudW1MaXRlPiBpbnRlcm5hbFZhbHVlTWFwID0KICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPEZvcmVpZ25FbnVtTGl0ZT4oKSB7CiAgICAgICAgICAgIHB1YmxpYyBGb3JlaWduRW51bUxpdGUgZmluZFZhbHVlQnlOdW1iZXIoaW50IG51bWJlcikgewogICAgICAgICAgICAgIHJldHVybiBGb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKG51bWJlcik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CgogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvcgogICAgICAgIGdldFZhbHVlRGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKS5nZXRWYWx1ZXMoKS5nZXQob3JkaW5hbCgpKTsKICAgIH0KICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuZ2V0RGVzY3JpcHRvcigpLmdldEVudW1UeXBlcygpLmdldCgwKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBGb3JlaWduRW51bUxpdGVbXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICBwdWJsaWMgc3RhdGljIEZvcmVpZ25FbnVtTGl0ZSB2YWx1ZU9mKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvciBkZXNjKSB7CiAgICAgIGlmIChkZXNjLmdldFR5cGUoKSAhPSBnZXREZXNjcmlwdG9yKCkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigKICAgICAgICAgICJFbnVtVmFsdWVEZXNjcmlwdG9yIGlzIG5vdCBmb3IgdGhpcyB0eXBlLiIpOwogICAgICB9CiAgICAgIHJldHVybiBWQUxVRVNbZGVzYy5nZXRJbmRleCgpXTsKICAgIH0KCiAgICBwcml2YXRlIGZpbmFsIGludCB2YWx1ZTsKCiAgICBwcml2YXRlIEZvcmVpZ25FbnVtTGl0ZShpbnQgdmFsdWUpIHsKICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChlbnVtX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSkKICB9CgogIC8qKgogICAqIFByb3RvYnVmIGVudW0ge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlYxRW51bUxpdGV9CiAgICovCiAgcHVibGljIGVudW0gVjFFbnVtTGl0ZQogICAgICBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xNZXNzYWdlRW51bSB7CiAgICAvKioKICAgICAqIDxjb2RlPlYxX0ZJUlNUID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIFYxX0ZJUlNUKDEpLAogICAgOwoKICAgIC8qKgogICAgICogPGNvZGU+VjFfRklSU1QgPSAxOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgVjFfRklSU1RfVkFMVUUgPSAxOwoKCiAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgc3RhdGljIFYxRW51bUxpdGUgdmFsdWVPZihpbnQgdmFsdWUpIHsKICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBWMUVudW1MaXRlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgIGNhc2UgMTogcmV0dXJuIFYxX0ZJUlNUOwogICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPFYxRW51bUxpdGU+CiAgICAgICAgaW50ZXJuYWxHZXRWYWx1ZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsVmFsdWVNYXA7CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPAogICAgICAgIFYxRW51bUxpdGU+IGludGVybmFsVmFsdWVNYXAgPQogICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8VjFFbnVtTGl0ZT4oKSB7CiAgICAgICAgICAgIHB1YmxpYyBWMUVudW1MaXRlIGZpbmRWYWx1ZUJ5TnVtYmVyKGludCBudW1iZXIpIHsKICAgICAgICAgICAgICByZXR1cm4gVjFFbnVtTGl0ZS5mb3JOdW1iZXIobnVtYmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKCiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yCiAgICAgICAgZ2V0VmFsdWVEZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpLmdldFZhbHVlcygpLmdldChvcmRpbmFsKCkpOwogICAgfQogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5nZXREZXNjcmlwdG9yKCkuZ2V0RW51bVR5cGVzKCkuZ2V0KDEpOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIFYxRW51bUxpdGVbXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICBwdWJsaWMgc3RhdGljIFYxRW51bUxpdGUgdmFsdWVPZigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IgZGVzYykgewogICAgICBpZiAoZGVzYy5nZXRUeXBlKCkgIT0gZ2V0RGVzY3JpcHRvcigpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAiRW51bVZhbHVlRGVzY3JpcHRvciBpcyBub3QgZm9yIHRoaXMgdHlwZS4iKTsKICAgICAgfQogICAgICByZXR1cm4gVkFMVUVTW2Rlc2MuZ2V0SW5kZXgoKV07CiAgICB9CgogICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CgogICAgcHJpdmF0ZSBWMUVudW1MaXRlKGludCB2YWx1ZSkgewogICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGVudW1fc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVjFFbnVtTGl0ZSkKICB9CgogIC8qKgogICAqIFByb3RvYnVmIGVudW0ge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlYyRW51bUxpdGV9CiAgICovCiAgcHVibGljIGVudW0gVjJFbnVtTGl0ZQogICAgICBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xNZXNzYWdlRW51bSB7CiAgICAvKioKICAgICAqIDxjb2RlPlYyX0ZJUlNUID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIFYyX0ZJUlNUKDEpLAogICAgLyoqCiAgICAgKiA8Y29kZT5WMl9TRUNPTkQgPSAyOzwvY29kZT4KICAgICAqLwogICAgVjJfU0VDT05EKDIpLAogICAgOwoKICAgIC8qKgogICAgICogPGNvZGU+VjJfRklSU1QgPSAxOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgVjJfRklSU1RfVkFMVUUgPSAxOwogICAgLyoqCiAgICAgKiA8Y29kZT5WMl9TRUNPTkQgPSAyOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgVjJfU0VDT05EX1ZBTFVFID0gMjsKCgogICAgcHVibGljIGZpbmFsIGludCBnZXROdW1iZXIoKSB7CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjZm9yTnVtYmVyKGludCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIHN0YXRpYyBWMkVudW1MaXRlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgIHJldHVybiBmb3JOdW1iZXIodmFsdWUpOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgVjJFbnVtTGl0ZSBmb3JOdW1iZXIoaW50IHZhbHVlKSB7CiAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICBjYXNlIDE6IHJldHVybiBWMl9GSVJTVDsKICAgICAgICBjYXNlIDI6IHJldHVybiBWMl9TRUNPTkQ7CiAgICAgICAgZGVmYXVsdDogcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8VjJFbnVtTGl0ZT4KICAgICAgICBpbnRlcm5hbEdldFZhbHVlTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxWYWx1ZU1hcDsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8CiAgICAgICAgVjJFbnVtTGl0ZT4gaW50ZXJuYWxWYWx1ZU1hcCA9CiAgICAgICAgICBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxWMkVudW1MaXRlPigpIHsKICAgICAgICAgICAgcHVibGljIFYyRW51bUxpdGUgZmluZFZhbHVlQnlOdW1iZXIoaW50IG51bWJlcikgewogICAgICAgICAgICAgIHJldHVybiBWMkVudW1MaXRlLmZvck51bWJlcihudW1iZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IKICAgICAgICBnZXRWYWx1ZURlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCkuZ2V0VmFsdWVzKCkuZ2V0KG9yZGluYWwoKSk7CiAgICB9CiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMik7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgVjJFbnVtTGl0ZVtdIFZBTFVFUyA9IHZhbHVlcygpOwoKICAgIHB1YmxpYyBzdGF0aWMgVjJFbnVtTGl0ZSB2YWx1ZU9mKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvciBkZXNjKSB7CiAgICAgIGlmIChkZXNjLmdldFR5cGUoKSAhPSBnZXREZXNjcmlwdG9yKCkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigKICAgICAgICAgICJFbnVtVmFsdWVEZXNjcmlwdG9yIGlzIG5vdCBmb3IgdGhpcyB0eXBlLiIpOwogICAgICB9CiAgICAgIHJldHVybiBWQUxVRVNbZGVzYy5nZXRJbmRleCgpXTsKICAgIH0KCiAgICBwcml2YXRlIGZpbmFsIGludCB2YWx1ZTsKCiAgICBwcml2YXRlIFYyRW51bUxpdGUoaW50IHZhbHVlKSB7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5WMkVudW1MaXRlKQogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogU2luZ3VsYXIKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsSW50MzIoKTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFNpbmd1bGFyCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBvcHRpb25hbF9pbnQzMiA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbnQzMi4KICAgICAqLwogICAgaW50IGdldE9wdGlvbmFsSW50MzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IG9wdGlvbmFsX2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW50NjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsSW50NjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgb3B0aW9uYWxfaW50NjQgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW50NjQuCiAgICAgKi8KICAgIGxvbmcgZ2V0T3B0aW9uYWxJbnQ2NCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIG9wdGlvbmFsX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFVpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxVaW50MzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIG9wdGlvbmFsX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxVaW50MzIuCiAgICAgKi8KICAgIGludCBnZXRPcHRpb25hbFVpbnQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IG9wdGlvbmFsX3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFVpbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxVaW50NjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IG9wdGlvbmFsX3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxVaW50NjQuCiAgICAgKi8KICAgIGxvbmcgZ2V0T3B0aW9uYWxVaW50NjQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQzMiBvcHRpb25hbF9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsU2ludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQzMiBvcHRpb25hbF9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ludDMyLgogICAgICovCiAgICBpbnQgZ2V0T3B0aW9uYWxTaW50MzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBvcHRpb25hbF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTaW50NjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsU2ludDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBvcHRpb25hbF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ludDY0LgogICAgICovCiAgICBsb25nIGdldE9wdGlvbmFsU2ludDY0KCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIG9wdGlvbmFsX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxGaXhlZDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEZpeGVkMzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBvcHRpb25hbF9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZpeGVkMzIuCiAgICAgKi8KICAgIGludCBnZXRPcHRpb25hbEZpeGVkMzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgb3B0aW9uYWxfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsRml4ZWQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IG9wdGlvbmFsX2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRml4ZWQ2NC4KICAgICAqLwogICAgbG9uZyBnZXRPcHRpb25hbEZpeGVkNjQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIG9wdGlvbmFsX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU2ZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsU2ZpeGVkMzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgb3B0aW9uYWxfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ZpeGVkMzIuCiAgICAgKi8KICAgIGludCBnZXRPcHRpb25hbFNmaXhlZDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBvcHRpb25hbF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTZml4ZWQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxTZml4ZWQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBvcHRpb25hbF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ZpeGVkNjQuCiAgICAgKi8KICAgIGxvbmcgZ2V0T3B0aW9uYWxTZml4ZWQ2NCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgb3B0aW9uYWxfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRmxvYXQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsRmxvYXQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgb3B0aW9uYWxfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZsb2F0LgogICAgICovCiAgICBmbG9hdCBnZXRPcHRpb25hbEZsb2F0KCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgb3B0aW9uYWxfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbERvdWJsZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxEb3VibGUoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIG9wdGlvbmFsX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRG91YmxlLgogICAgICovCiAgICBkb3VibGUgZ2V0T3B0aW9uYWxEb3VibGUoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgb3B0aW9uYWxfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxCb29sIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEJvb2woKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBvcHRpb25hbF9ib29sID0gMTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxCb29sLgogICAgICovCiAgICBib29sZWFuIGdldE9wdGlvbmFsQm9vbCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFN0cmluZy4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRPcHRpb25hbFN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9wdGlvbmFsU3RyaW5nLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPcHRpb25hbFN0cmluZ0J5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxCeXRlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQnl0ZXMuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPcHRpb25hbEJ5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxncm91cCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsZ3JvdXAuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxNiB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXIgZ2V0T3B0aW9uYWxHcm91cE9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTmVzdGVkTWVzc2FnZS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxGb3JlaWduTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZU9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxJbXBvcnRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEltcG9ydE1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW1wb3J0TWVzc2FnZS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZU9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBvcHRpb25hbF9uZXN0ZWRfZW51bSA9IDIxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxOZXN0ZWRFbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbE5lc3RlZEVudW0oKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBvcHRpb25hbF9uZXN0ZWRfZW51bSA9IDIxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTmVzdGVkRW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGdldE9wdGlvbmFsTmVzdGVkRW51bSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9mb3JlaWduX2VudW0gPSAyMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRm9yZWlnbkVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsRm9yZWlnbkVudW0oKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9mb3JlaWduX2VudW0gPSAyMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZvcmVpZ25FbnVtLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgZ2V0T3B0aW9uYWxGb3JlaWduRW51bSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBvcHRpb25hbF9pbXBvcnRfZW51bSA9IDIzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxJbXBvcnRFbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEltcG9ydEVudW0oKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBvcHRpb25hbF9pbXBvcnRfZW51bSA9IDIzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW1wb3J0RW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0T3B0aW9uYWxJbXBvcnRFbnVtKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nX3BpZWNlID0gMjQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU3RyaW5nUGllY2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nUGllY2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZ19waWVjZSA9IDI0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTdHJpbmdQaWVjZS4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRPcHRpb25hbFN0cmluZ1BpZWNlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZ1BpZWNlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPcHRpb25hbFN0cmluZ1BpZWNlQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9jb3JkID0gMjUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbENvcmQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsQ29yZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQ29yZC4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRPcHRpb25hbENvcmQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX2NvcmQgPSAyNSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxDb3JkLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPcHRpb25hbENvcmRCeXRlcygpOwoKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIERlZmluZWQgaW4gdW5pdHRlc3RfaW1wb3J0X3B1YmxpYy5wcm90bwogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2UgPSAyNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIERlZmluZWQgaW4gdW5pdHRlc3RfaW1wb3J0X3B1YmxpYy5wcm90bwogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2UgPSAyNjs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZU9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxMYXp5TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxMYXp5TWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxMYXp5TWVzc2FnZS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF91bnZlcmlmaWVkX2xhenlfbWVzc2FnZSA9IDI4IFt1bnZlcmlmaWVkX2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBSZXBlYXRlZAogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAzMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFJlcGVhdGVkCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDMxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEludDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFJlcGVhdGVkCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDMxOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCByZXBlYXRlZF9pbnQ2NCA9IDMyOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50NjQuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPiBnZXRSZXBlYXRlZEludDY0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCByZXBlYXRlZF9pbnQ2NCA9IDMyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50NjQuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEludDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcmVwZWF0ZWRfaW50NjQgPSAzMjs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBsb25nIGdldFJlcGVhdGVkSW50NjQoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiByZXBlYXRlZF91aW50MzIgPSAzMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFVpbnQzMi4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IGdldFJlcGVhdGVkVWludDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcmVwZWF0ZWRfdWludDMyID0gMzM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRVaW50MzIuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFVpbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiByZXBlYXRlZF91aW50MzIgPSAzMzs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkVWludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkVWludDMyKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcmVwZWF0ZWRfdWludDY0ID0gMzQ7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRVaW50NjQuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPiBnZXRSZXBlYXRlZFVpbnQ2NExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHJlcGVhdGVkX3VpbnQ2NCA9IDM0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkVWludDY0LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRVaW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcmVwZWF0ZWRfdWludDY0ID0gMzQ7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFVpbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGxvbmcgZ2V0UmVwZWF0ZWRVaW50NjQoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiByZXBlYXRlZF9zaW50MzIgPSAzNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFNpbnQzMi4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IGdldFJlcGVhdGVkU2ludDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcmVwZWF0ZWRfc2ludDMyID0gMzU7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTaW50MzIuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFNpbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiByZXBlYXRlZF9zaW50MzIgPSAzNTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU2ludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkU2ludDMyKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcmVwZWF0ZWRfc2ludDY0ID0gMzY7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTaW50NjQuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPiBnZXRSZXBlYXRlZFNpbnQ2NExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHJlcGVhdGVkX3NpbnQ2NCA9IDM2OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU2ludDY0LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRTaW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcmVwZWF0ZWRfc2ludDY0ID0gMzY7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFNpbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGxvbmcgZ2V0UmVwZWF0ZWRTaW50NjQoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDM3OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQzMi4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMzc7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMzc7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHJlcGVhdGVkX2ZpeGVkNjQgPSAzODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZpeGVkNjQuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPiBnZXRSZXBlYXRlZEZpeGVkNjRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRml4ZWQ2NC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkRml4ZWQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGaXhlZDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgbG9uZyBnZXRSZXBlYXRlZEZpeGVkNjQoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHJlcGVhdGVkX3NmaXhlZDMyID0gMzk7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTZml4ZWQzMi4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IGdldFJlcGVhdGVkU2ZpeGVkMzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHJlcGVhdGVkX3NmaXhlZDMyID0gMzk7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTZml4ZWQzMi4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkU2ZpeGVkMzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiByZXBlYXRlZF9zZml4ZWQzMiA9IDM5OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTZml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFNmaXhlZDMyKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCByZXBlYXRlZF9zZml4ZWQ2NCA9IDQwOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU2ZpeGVkNjQuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPiBnZXRSZXBlYXRlZFNmaXhlZDY0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCByZXBlYXRlZF9zZml4ZWQ2NCA9IDQwOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU2ZpeGVkNjQuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFNmaXhlZDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcmVwZWF0ZWRfc2ZpeGVkNjQgPSA0MDs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU2ZpeGVkNjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBsb25nIGdldFJlcGVhdGVkU2ZpeGVkNjQoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHJlcGVhdGVkX2Zsb2F0ID0gNDE7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRGbG9hdC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkZsb2F0PiBnZXRSZXBlYXRlZEZsb2F0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCByZXBlYXRlZF9mbG9hdCA9IDQxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRmxvYXQuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEZsb2F0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcmVwZWF0ZWRfZmxvYXQgPSA0MTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRmxvYXQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBmbG9hdCBnZXRSZXBlYXRlZEZsb2F0KGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcmVwZWF0ZWRfZG91YmxlID0gNDI7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWREb3VibGUuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Eb3VibGU+IGdldFJlcGVhdGVkRG91YmxlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcmVwZWF0ZWRfZG91YmxlID0gNDI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWREb3VibGUuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZERvdWJsZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSByZXBlYXRlZF9kb3VibGUgPSA0Mjs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRG91YmxlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgZG91YmxlIGdldFJlcGVhdGVkRG91YmxlKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHJlcGVhdGVkX2Jvb2wgPSA0Mzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEJvb2wuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Cb29sZWFuPiBnZXRSZXBlYXRlZEJvb2xMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkQm9vbC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkQm9vbENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRCb29sIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgYm9vbGVhbiBnZXRSZXBlYXRlZEJvb2woaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFN0cmluZy4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLlN0cmluZz4KICAgICAgICBnZXRSZXBlYXRlZFN0cmluZ0xpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZyA9IDQ0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU3RyaW5nLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRTdHJpbmdDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nID0gNDQ7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFN0cmluZyBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0UmVwZWF0ZWRTdHJpbmcoaW50IGluZGV4KTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZyA9IDQ0OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHZhbHVlIHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZFN0cmluZyBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldFJlcGVhdGVkU3RyaW5nQnl0ZXMoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJ5dGVzIHJlcGVhdGVkX2J5dGVzID0gNDU7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRCeXRlcy4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBnZXRSZXBlYXRlZEJ5dGVzTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBieXRlcyByZXBlYXRlZF9ieXRlcyA9IDQ1OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkQnl0ZXMuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEJ5dGVzQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkQnl0ZXMgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0UmVwZWF0ZWRCeXRlcyhpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cD4gCiAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBnZXRSZXBlYXRlZEdyb3VwKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRHcm91cENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZEdyb3VwT3JCdWlsZGVyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyIGdldFJlcGVhdGVkR3JvdXBPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gCiAgICAgICAgZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IAogICAgICAgIGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZShpbnQgaW5kZXgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlT3JCdWlsZGVyKAogICAgICAgIGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZT4gCiAgICAgICAgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoaW50IGluZGV4KTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVwZWF0ZWRfbmVzdGVkX2VudW0gPSA1MTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZE5lc3RlZEVudW0uCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bT4gZ2V0UmVwZWF0ZWROZXN0ZWRFbnVtTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWROZXN0ZWRFbnVtLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWROZXN0ZWRFbnVtQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWROZXN0ZWRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGdldFJlcGVhdGVkTmVzdGVkRW51bShpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZvcmVpZ25FbnVtLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IGdldFJlcGVhdGVkRm9yZWlnbkVudW1MaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9lbnVtID0gNTI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGb3JlaWduRW51bS4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkRm9yZWlnbkVudW1Db3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHJlcGVhdGVkX2ZvcmVpZ25fZW51bSA9IDUyOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGb3JlaWduRW51bSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbXBvcnRFbnVtLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4gZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbXBvcnRFbnVtLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSByZXBlYXRlZF9pbXBvcnRfZW51bSA9IDUzOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbXBvcnRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFN0cmluZ1BpZWNlLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgIGdldFJlcGVhdGVkU3RyaW5nUGllY2VMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHZhbHVlIHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUJ5dGVzKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkQ29yZC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLlN0cmluZz4KICAgICAgICBnZXRSZXBlYXRlZENvcmRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRDb3JkLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRDb3JkQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX2NvcmQgPSA1NSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkQ29yZCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0UmVwZWF0ZWRDb3JkKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdmFsdWUgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkQ29yZCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldFJlcGVhdGVkQ29yZEJ5dGVzKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IAogICAgICAgIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRSZXBlYXRlZExhenlNZXNzYWdlKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZExhenlNZXNzYWdlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBTaW5ndWxhciB3aXRoIGRlZmF1bHRzCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWZhdWx0X2ludDMyID0gNjEgW2RlZmF1bHQgPSA0MV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0SW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRJbnQzMigpOwogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogU2luZ3VsYXIgd2l0aCBkZWZhdWx0cwogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVmYXVsdF9pbnQzMiA9IDYxIFtkZWZhdWx0ID0gNDFdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRJbnQzMi4KICAgICAqLwogICAgaW50IGdldERlZmF1bHRJbnQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgZGVmYXVsdF9pbnQ2NCA9IDYyIFtkZWZhdWx0ID0gNDJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEludDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0SW50NjQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgZGVmYXVsdF9pbnQ2NCA9IDYyIFtkZWZhdWx0ID0gNDJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRJbnQ2NC4KICAgICAqLwogICAgbG9uZyBnZXREZWZhdWx0SW50NjQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBkZWZhdWx0X3VpbnQzMiA9IDYzIFtkZWZhdWx0ID0gNDNdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFVpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdFVpbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgZGVmYXVsdF91aW50MzIgPSA2MyBbZGVmYXVsdCA9IDQzXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0VWludDMyLgogICAgICovCiAgICBpbnQgZ2V0RGVmYXVsdFVpbnQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IGRlZmF1bHRfdWludDY0ID0gNjQgW2RlZmF1bHQgPSA0NF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0VWludDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0VWludDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQ2NCBkZWZhdWx0X3VpbnQ2NCA9IDY0IFtkZWZhdWx0ID0gNDRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRVaW50NjQuCiAgICAgKi8KICAgIGxvbmcgZ2V0RGVmYXVsdFVpbnQ2NCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIGRlZmF1bHRfc2ludDMyID0gNjUgW2RlZmF1bHQgPSAtNDVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFNpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdFNpbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgZGVmYXVsdF9zaW50MzIgPSA2NSBbZGVmYXVsdCA9IC00NV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdFNpbnQzMi4KICAgICAqLwogICAgaW50IGdldERlZmF1bHRTaW50MzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBkZWZhdWx0X3NpbnQ2NCA9IDY2IFtkZWZhdWx0ID0gNDZdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFNpbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdFNpbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50NjQgZGVmYXVsdF9zaW50NjQgPSA2NiBbZGVmYXVsdCA9IDQ2XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U2ludDY0LgogICAgICovCiAgICBsb25nIGdldERlZmF1bHRTaW50NjQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkMzIgZGVmYXVsdF9maXhlZDMyID0gNjcgW2RlZmF1bHQgPSA0N107PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Rml4ZWQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdEZpeGVkMzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBkZWZhdWx0X2ZpeGVkMzIgPSA2NyBbZGVmYXVsdCA9IDQ3XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Rml4ZWQzMi4KICAgICAqLwogICAgaW50IGdldERlZmF1bHRGaXhlZDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IGRlZmF1bHRfZml4ZWQ2NCA9IDY4IFtkZWZhdWx0ID0gNDhdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRGaXhlZDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgZGVmYXVsdF9maXhlZDY0ID0gNjggW2RlZmF1bHQgPSA0OF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdEZpeGVkNjQuCiAgICAgKi8KICAgIGxvbmcgZ2V0RGVmYXVsdEZpeGVkNjQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIGRlZmF1bHRfc2ZpeGVkMzIgPSA2OSBbZGVmYXVsdCA9IDQ5XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTZml4ZWQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdFNmaXhlZDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIGRlZmF1bHRfc2ZpeGVkMzIgPSA2OSBbZGVmYXVsdCA9IDQ5XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U2ZpeGVkMzIuCiAgICAgKi8KICAgIGludCBnZXREZWZhdWx0U2ZpeGVkMzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IGRlZmF1bHRfc2ZpeGVkNjQgPSA3MCBbZGVmYXVsdCA9IC01MF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U2ZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRTZml4ZWQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBkZWZhdWx0X3NmaXhlZDY0ID0gNzAgW2RlZmF1bHQgPSAtNTBdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTZml4ZWQ2NC4KICAgICAqLwogICAgbG9uZyBnZXREZWZhdWx0U2ZpeGVkNjQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IGRlZmF1bHRfZmxvYXQgPSA3MSBbZGVmYXVsdCA9IDUxLjVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZsb2F0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNEZWZhdWx0RmxvYXQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgZGVmYXVsdF9mbG9hdCA9IDcxIFtkZWZhdWx0ID0gNTEuNV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdEZsb2F0LgogICAgICovCiAgICBmbG9hdCBnZXREZWZhdWx0RmxvYXQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBkZWZhdWx0X2RvdWJsZSA9IDcyIFtkZWZhdWx0ID0gNTIwMDBdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdERvdWJsZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdERvdWJsZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgZGVmYXVsdF9kb3VibGUgPSA3MiBbZGVmYXVsdCA9IDUyMDAwXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0RG91YmxlLgogICAgICovCiAgICBkb3VibGUgZ2V0RGVmYXVsdERvdWJsZSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBkZWZhdWx0X2Jvb2wgPSA3MyBbZGVmYXVsdCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEJvb2wgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRCb29sKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgZGVmYXVsdF9ib29sID0gNzMgW2RlZmF1bHQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Qm9vbC4KICAgICAqLwogICAgYm9vbGVhbiBnZXREZWZhdWx0Qm9vbCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U3RyaW5nLgogICAgICovCiAgICBqYXZhLmxhbmcuU3RyaW5nIGdldERlZmF1bHRTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVmYXVsdFN0cmluZy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0RGVmYXVsdFN0cmluZ0J5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBkZWZhdWx0X2J5dGVzID0gNzUgW2RlZmF1bHQgPSAid29ybGQiXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdEJ5dGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIGRlZmF1bHRfYnl0ZXMgPSA3NSBbZGVmYXVsdCA9ICJ3b3JsZCJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRCeXRlcy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldERlZmF1bHRCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBkZWZhdWx0X25lc3RlZF9lbnVtID0gODEgW2RlZmF1bHQgPSBCQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdE5lc3RlZEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHROZXN0ZWRFbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gZGVmYXVsdF9uZXN0ZWRfZW51bSA9IDgxIFtkZWZhdWx0ID0gQkFSXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0TmVzdGVkRW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGdldERlZmF1bHROZXN0ZWRFbnVtKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIGRlZmF1bHRfZm9yZWlnbl9lbnVtID0gODIgW2RlZmF1bHQgPSBGT1JFSUdOX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRGb3JlaWduRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdEZvcmVpZ25FbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGb3JlaWduRW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldERlZmF1bHRGb3JlaWduRW51bSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBkZWZhdWx0X2ltcG9ydF9lbnVtID0gODMgW2RlZmF1bHQgPSBJTVBPUlRfTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEltcG9ydEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0RlZmF1bHRJbXBvcnRFbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgZGVmYXVsdF9pbXBvcnRfZW51bSA9IDgzIFtkZWZhdWx0ID0gSU1QT1JUX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0SW1wb3J0RW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0RGVmYXVsdEltcG9ydEVudW0oKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTdHJpbmdQaWVjZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdFN0cmluZ1BpZWNlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U3RyaW5nUGllY2UuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdFN0cmluZ1BpZWNlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVmYXVsdFN0cmluZ1BpZWNlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZWZhdWx0U3RyaW5nUGllY2VCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Q29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVmYXVsdENvcmQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdENvcmQuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdENvcmQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlZmF1bHRDb3JkLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZWZhdWx0Q29yZEJ5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gMTExOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mVWludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSAxMTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZVaW50MzIuCiAgICAgKi8KICAgIGludCBnZXRPbmVvZlVpbnQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mTmVzdGVkTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZOZXN0ZWRNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZOZXN0ZWRNZXNzYWdlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mU3RyaW5nKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAxMTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9uZW9mU3RyaW5nQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gMTE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZCeXRlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDExNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9sYXp5X25lc3RlZF9tZXNzYWdlID0gMTE1IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG9uZW9mX25lc3RlZF9tZXNzYWdlMiA9IDExNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mTmVzdGVkTWVzc2FnZTIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mTmVzdGVkTWVzc2FnZTIoKTsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mTmVzdGVkTWVzc2FnZTIuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyIGdldE9uZW9mTmVzdGVkTWVzc2FnZTJPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBUZXN0cyB0b1N0cmluZyBmb3Igbm9uLXJlcGVhdGVkIGZpZWxkcyB3aXRoIGEgbGlzdCBzdWZmaXgKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlY2VwdGl2ZWx5X25hbWVkX2xpc3QgPSAxMTY7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRGVjZXB0aXZlbHlOYW1lZExpc3QoKTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRlc3RzIHRvU3RyaW5nIGZvciBub24tcmVwZWF0ZWQgZmllbGRzIHdpdGggYSBsaXN0IHN1ZmZpeAogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVjZXB0aXZlbHlfbmFtZWRfbGlzdCA9IDExNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdC4KICAgICAqLwogICAgaW50IGdldERlY2VwdGl2ZWx5TmFtZWRMaXN0KCk7CgogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PbmVvZkZpZWxkQ2FzZSBnZXRPbmVvZkZpZWxkQ2FzZSgpOwogIH0KICAvKioKICAgKiA8cHJlPgogICAqIFNhbWUgYXMgVGVzdEFsbFR5cGVzIGJ1dCB3aXRoIHRoZSBsaXRlIHJ1bnRpbWUuCiAgICogPC9wcmU+CiAgICoKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdEFsbFR5cGVzTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlKQogICAgICBUZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0QWxsVHlwZXNMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RBbGxUeXBlc0xpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0QWxsVHlwZXNMaXRlKCkgewogICAgICBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgICAgb3B0aW9uYWxCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFk7CiAgICAgIG9wdGlvbmFsTmVzdGVkRW51bV8gPSAxOwogICAgICBvcHRpb25hbEZvcmVpZ25FbnVtXyA9IDQ7CiAgICAgIG9wdGlvbmFsSW1wb3J0RW51bV8gPSA3OwogICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9ICIiOwogICAgICBvcHRpb25hbENvcmRfID0gIiI7CiAgICAgIHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHJlcGVhdGVkSW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICByZXBlYXRlZFVpbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcmVwZWF0ZWRVaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICByZXBlYXRlZFNpbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcmVwZWF0ZWRTaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICByZXBlYXRlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHJlcGVhdGVkRml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHJlcGVhdGVkU2ZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHJlcGVhdGVkU2ZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICByZXBlYXRlZEZsb2F0XyA9IGVtcHR5RmxvYXRMaXN0KCk7CiAgICAgIHJlcGVhdGVkRG91YmxlXyA9IGVtcHR5RG91YmxlTGlzdCgpOwogICAgICByZXBlYXRlZEJvb2xfID0gZW1wdHlCb29sZWFuTGlzdCgpOwogICAgICByZXBlYXRlZFN0cmluZ18gPQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgICByZXBlYXRlZEJ5dGVzXyA9IGVtcHR5TGlzdChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY2xhc3MpOwogICAgICByZXBlYXRlZEdyb3VwXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkTmVzdGVkRW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkRm9yZWlnbkVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICByZXBlYXRlZEltcG9ydEVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICByZXBlYXRlZFN0cmluZ1BpZWNlXyA9CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgIHJlcGVhdGVkQ29yZF8gPQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgICByZXBlYXRlZExhenlNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgZGVmYXVsdEludDMyXyA9IDQxOwogICAgICBkZWZhdWx0SW50NjRfID0gNDJMOwogICAgICBkZWZhdWx0VWludDMyXyA9IDQzOwogICAgICBkZWZhdWx0VWludDY0XyA9IDQ0TDsKICAgICAgZGVmYXVsdFNpbnQzMl8gPSAtNDU7CiAgICAgIGRlZmF1bHRTaW50NjRfID0gNDZMOwogICAgICBkZWZhdWx0Rml4ZWQzMl8gPSA0NzsKICAgICAgZGVmYXVsdEZpeGVkNjRfID0gNDhMOwogICAgICBkZWZhdWx0U2ZpeGVkMzJfID0gNDk7CiAgICAgIGRlZmF1bHRTZml4ZWQ2NF8gPSAtNTBMOwogICAgICBkZWZhdWx0RmxvYXRfID0gNTEuNUY7CiAgICAgIGRlZmF1bHREb3VibGVfID0gNTIwMDBEOwogICAgICBkZWZhdWx0Qm9vbF8gPSB0cnVlOwogICAgICBkZWZhdWx0U3RyaW5nXyA9ICJoZWxsbyI7CiAgICAgIGRlZmF1bHRCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmJ5dGVzRGVmYXVsdFZhbHVlKCJ3b3JsZCIpOwogICAgICBkZWZhdWx0TmVzdGVkRW51bV8gPSAyOwogICAgICBkZWZhdWx0Rm9yZWlnbkVudW1fID0gNTsKICAgICAgZGVmYXVsdEltcG9ydEVudW1fID0gODsKICAgICAgZGVmYXVsdFN0cmluZ1BpZWNlXyA9ICJhYmMiOwogICAgICBkZWZhdWx0Q29yZF8gPSAiMTIzIjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0QWxsVHlwZXNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgLyoqCiAgICAgKiBQcm90b2J1ZiBlbnVtIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW19CiAgICAgKi8KICAgIHB1YmxpYyBlbnVtIE5lc3RlZEVudW0KICAgICAgICBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xNZXNzYWdlRW51bSB7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5GT08gPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEZPTygxKSwKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkJBUiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQkFSKDIpLAogICAgICAvKioKICAgICAgICogPGNvZGU+QkFaID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBCQVooMyksCiAgICAgIDsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5GT08gPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZPT19WQUxVRSA9IDE7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5CQVIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEJBUl9WQUxVRSA9IDI7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5CQVogPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEJBWl9WQUxVRSA9IDM7CgoKICAgICAgcHVibGljIGZpbmFsIGludCBnZXROdW1iZXIoKSB7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9CgogICAgICAvKioKICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjZm9yTnVtYmVyKGludCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIHN0YXRpYyBOZXN0ZWRFbnVtIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBOZXN0ZWRFbnVtIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgICBzd2l0Y2ggKHZhbHVlKSB7CiAgICAgICAgICBjYXNlIDE6IHJldHVybiBGT087CiAgICAgICAgICBjYXNlIDI6IHJldHVybiBCQVI7CiAgICAgICAgICBjYXNlIDM6IHJldHVybiBCQVo7CiAgICAgICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxOZXN0ZWRFbnVtPgogICAgICAgICAgaW50ZXJuYWxHZXRWYWx1ZU1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxWYWx1ZU1hcDsKICAgICAgfQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPAogICAgICAgICAgTmVzdGVkRW51bT4gaW50ZXJuYWxWYWx1ZU1hcCA9CiAgICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPE5lc3RlZEVudW0+KCkgewogICAgICAgICAgICAgIHB1YmxpYyBOZXN0ZWRFbnVtIGZpbmRWYWx1ZUJ5TnVtYmVyKGludCBudW1iZXIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBOZXN0ZWRFbnVtLmZvck51bWJlcihudW1iZXIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfTsKCiAgICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IKICAgICAgICAgIGdldFZhbHVlRGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpLmdldFZhbHVlcygpLmdldChvcmRpbmFsKCkpOwogICAgICB9CiAgICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZXNjcmlwdG9yKCkuZ2V0RW51bVR5cGVzKCkuZ2V0KDApOwogICAgICB9CgogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBOZXN0ZWRFbnVtW10gVkFMVUVTID0gdmFsdWVzKCk7CgogICAgICBwdWJsaWMgc3RhdGljIE5lc3RlZEVudW0gdmFsdWVPZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvciBkZXNjKSB7CiAgICAgICAgaWYgKGRlc2MuZ2V0VHlwZSgpICE9IGdldERlc2NyaXB0b3IoKSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAgICJFbnVtVmFsdWVEZXNjcmlwdG9yIGlzIG5vdCBmb3IgdGhpcyB0eXBlLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gVkFMVUVTW2Rlc2MuZ2V0SW5kZXgoKV07CiAgICAgIH0KCiAgICAgIHByaXZhdGUgZmluYWwgaW50IHZhbHVlOwoKICAgICAgcHJpdmF0ZSBOZXN0ZWRFbnVtKGludCB2YWx1ZSkgewogICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgICAgfQoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGVudW1fc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtKQogICAgfQoKICAgIHB1YmxpYyBpbnRlcmZhY2UgTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGJiID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYmIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgYm9vbGVhbiBoYXNCYigpOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYmIgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYmIuCiAgICAgICAqLwogICAgICBpbnQgZ2V0QmIoKTsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBjYyA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGNjIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIGJvb2xlYW4gaGFzQ2MoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGNjID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNjLgogICAgICAgKi8KICAgICAgbG9uZyBnZXRDYygpOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBkZC4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXREZExpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBkZC4KICAgICAgICovCiAgICAgIGludCBnZXREZENvdW50KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIGRkIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIGludCBnZXREZChpbnQgaW5kZXgpOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2V9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgTmVzdGVkTWVzc2FnZSBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKQogICAgICAgIE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAgIC8vIFVzZSBOZXN0ZWRNZXNzYWdlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgIHByaXZhdGUgTmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgfQogICAgICBwcml2YXRlIE5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgZGRfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICAgIHJldHVybiBuZXcgTmVzdGVkTWVzc2FnZSgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBCQl9GSUVMRF9OVU1CRVIgPSAxOwogICAgICBwcml2YXRlIGludCBiYl8gPSAwOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYmIgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBiYiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0JiKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYmIgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYmIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0QmIoKSB7CiAgICAgICAgcmV0dXJuIGJiXzsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgQ0NfRklFTERfTlVNQkVSID0gMjsKICAgICAgcHJpdmF0ZSBsb25nIGNjXyA9IDBMOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgY2MgPSAyOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBjYyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0NjKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgY2MgPSAyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY2MuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldENjKCkgewogICAgICAgIHJldHVybiBjY187CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEREX0ZJRUxEX05VTUJFUiA9IDM7CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCBkZF8gPQogICAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgZGQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldERkTGlzdCgpIHsKICAgICAgICByZXR1cm4gZGRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgZGQuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldERkQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGRkXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgZGQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXREZChpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZGRfLmdldEludChpbmRleCk7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgZGRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigxLCBiYl8pOwogICAgICAgIH0KICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIG91dHB1dC53cml0ZUludDY0KDIsIGNjXyk7CiAgICAgICAgfQogICAgICAgIGlmIChnZXREZExpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZygyNik7CiAgICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhkZE1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGRkXy5zaXplKCk7IGkrKykgewogICAgICAgICAgb3V0cHV0LndyaXRlSW50MzJOb1RhZyhkZF8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgICAgc2l6ZSA9IDA7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMSwgYmJfKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQ2NFNpemUoMiwgY2NfKTsKICAgICAgICB9CiAgICAgICAgewogICAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZGRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRkXy5nZXRJbnQoaSkpOwogICAgICAgICAgfQogICAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICAgIGlmICghZ2V0RGRMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHNpemUgKz0gMTsKICAgICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICAgIH0KICAgICAgICAgIGRkTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgICAgcmV0dXJuIHNpemU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgICAgfQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9iajsKCiAgICAgICAgaWYgKGhhc0JiKCkgIT0gb3RoZXIuaGFzQmIoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChoYXNCYigpKSB7CiAgICAgICAgICBpZiAoZ2V0QmIoKQogICAgICAgICAgICAgICE9IG90aGVyLmdldEJiKCkpIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKGhhc0NjKCkgIT0gb3RoZXIuaGFzQ2MoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChoYXNDYygpKSB7CiAgICAgICAgICBpZiAoZ2V0Q2MoKQogICAgICAgICAgICAgICE9IG90aGVyLmdldENjKCkpIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFnZXREZExpc3QoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldERkTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgICB9CiAgICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgICBpZiAoaGFzQmIoKSkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgQkJfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0QmIoKTsKICAgICAgICB9CiAgICAgICAgaWYgKGhhc0NjKCkpIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIENDX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgICAgZ2V0Q2MoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChnZXREZENvdW50KCkgPiAwKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERF9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZExpc3QoKS5oYXNoQ29kZSgpOwogICAgICAgIH0KICAgICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgICByZXR1cm4gaGFzaDsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcHJvdG90eXBlKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgewogICAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLm5ld0J1aWxkZXIoKQogICAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgICAgYmJfID0gMDsKICAgICAgICAgIGNjXyA9IDBMOwogICAgICAgICAgZGRfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2VfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgYnVpbGQoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSh0aGlzKTsKICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlc3VsdCkgewogICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICByZXN1bHQuYmJfID0gYmJfOwogICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgICByZXN1bHQuY2NfID0gY2NfOwogICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgICBkZF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICByZXN1bHQuZGRfID0gZGRfOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgewogICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Upb3RoZXIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICAgIGlmIChvdGhlci5oYXNCYigpKSB7CiAgICAgICAgICAgIHNldEJiKG90aGVyLmdldEJiKCkpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG90aGVyLmhhc0NjKCkpIHsKICAgICAgICAgICAgc2V0Q2Mob3RoZXIuZ2V0Q2MoKSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIW90aGVyLmRkXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKGRkXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBkZF8gPSBvdGhlci5kZF87CiAgICAgICAgICAgICAgZGRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZW5zdXJlRGRJc011dGFibGUoKTsKICAgICAgICAgICAgICBkZF8uYWRkQWxsKG90aGVyLmRkXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgICAgYmJfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgICAgY2FzZSAxNjogewogICAgICAgICAgICAgICAgICBjY18gPSBpbnB1dC5yZWFkSW50NjQoKTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxNgogICAgICAgICAgICAgICAgY2FzZSAyNDogewogICAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgICBlbnN1cmVEZElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICBkZF8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAyNAogICAgICAgICAgICAgICAgY2FzZSAyNjogewogICAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgICBlbnN1cmVEZElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgZGRfLmFkZEludChpbnB1dC5yZWFkSW50MzIoKSk7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAyNgogICAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgICAgcHJpdmF0ZSBpbnQgYmJfIDsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBiYiA9IDE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYmIgZmllbGQgaXMgc2V0LgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgYm9vbGVhbiBoYXNCYigpIHsKICAgICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYmIgPSAxOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBiYi4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGludCBnZXRCYigpIHsKICAgICAgICAgIHJldHVybiBiYl87CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGJiID0gMTs8L2NvZGU+CiAgICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBiYiB0byBzZXQuCiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEJiKGludCB2YWx1ZSkgewoKICAgICAgICAgIGJiXyA9IHZhbHVlOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYmIgPSAxOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJCYigpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgIGJiXyA9IDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBsb25nIGNjXyA7CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgY2MgPSAyOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGNjIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzQ2MoKSB7CiAgICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGNjID0gMjs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgY2MuCiAgICAgICAgICovCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBsb25nIGdldENjKCkgewogICAgICAgICAgcmV0dXJuIGNjXzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgY2MgPSAyOzwvY29kZT4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGNjIHRvIHNldC4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0Q2MobG9uZyB2YWx1ZSkgewoKICAgICAgICAgIGNjXyA9IHZhbHVlOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgY2MgPSAyOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJDYygpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICAgIGNjXyA9IDBMOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IGRkXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVEZElzTXV0YWJsZSgpIHsKICAgICAgICAgIGlmICghZGRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICAgIGRkXyA9IG1ha2VNdXRhYmxlQ29weShkZF8pOwogICAgICAgICAgfQogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBkZC4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgIGdldERkTGlzdCgpIHsKICAgICAgICAgIGRkXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXR1cm4gZGRfOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBkZC4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgaW50IGdldERkQ291bnQoKSB7CiAgICAgICAgICByZXR1cm4gZGRfLnNpemUoKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgZGQgPSAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAgICogQHJldHVybiBUaGUgZGQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBpbnQgZ2V0RGQoaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZGRfLmdldEludChpbmRleCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRkIHRvIHNldC4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGQoCiAgICAgICAgICAgIGludCBpbmRleCwgaW50IHZhbHVlKSB7CgogICAgICAgICAgZW5zdXJlRGRJc011dGFibGUoKTsKICAgICAgICAgIGRkXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIGRkID0gMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGQgdG8gYWRkLgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGREZChpbnQgdmFsdWUpIHsKCiAgICAgICAgICBlbnN1cmVEZElzTXV0YWJsZSgpOwogICAgICAgICAgZGRfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBkZCA9IDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBkZCB0byBhZGQuCiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbERkKAogICAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICAgIGVuc3VyZURkSXNNdXRhYmxlKCk7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgICAgdmFsdWVzLCBkZF8pOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgZGQgPSAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGQoKSB7CiAgICAgICAgICBkZF8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKQogICAgICB9CgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgREVGQVVMVF9JTlNUQU5DRTsKICAgICAgc3RhdGljIHsKICAgICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE5lc3RlZE1lc3NhZ2U+CiAgICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxOZXN0ZWRNZXNzYWdlPigpIHsKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIE5lc3RlZE1lc3NhZ2UgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOZXN0ZWRNZXNzYWdlPiBwYXJzZXIoKSB7CiAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8TmVzdGVkTWVzc2FnZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgIH0KCiAgICBwdWJsaWMgaW50ZXJmYWNlIE5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgYm9vbGVhbiBoYXNEZCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGQuCiAgICAgICAqLwogICAgICBpbnQgZ2V0RGQoKTsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMn0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBOZXN0ZWRNZXNzYWdlMiBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikKICAgICAgICBOZXN0ZWRNZXNzYWdlMk9yQnVpbGRlciB7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgICAgLy8gVXNlIE5lc3RlZE1lc3NhZ2UyLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgIHByaXZhdGUgTmVzdGVkTWVzc2FnZTIoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBOZXN0ZWRNZXNzYWdlMigpIHsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgICAgcmV0dXJuIG5ldyBOZXN0ZWRNZXNzYWdlMigpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZTJfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZTJfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRERfRklFTERfTlVNQkVSID0gMTsKICAgICAgcHJpdmF0ZSBpbnQgZGRfID0gMDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldERkKCkgewogICAgICAgIHJldHVybiBkZF87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigxLCBkZF8pOwogICAgICAgIH0KICAgICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgICBzaXplID0gMDsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBkZF8pOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgICAgcmV0dXJuIHNpemU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICAgIH0KICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpIG9iajsKCiAgICAgICAgaWYgKGhhc0RkKCkgIT0gb3RoZXIuaGFzRGQoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChoYXNEZCgpKSB7CiAgICAgICAgICBpZiAoZ2V0RGQoKQogICAgICAgICAgICAgICE9IG90aGVyLmdldERkKCkpIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICAgIH0KICAgICAgICBpbnQgaGFzaCA9IDQxOwogICAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICAgIGlmIChoYXNEZCgpKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERF9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZCgpOwogICAgICAgIH0KICAgICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgICByZXR1cm4gaGFzaDsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBwYXJzZUZyb20oCiAgICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHByb3RvdHlwZSkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTJ9CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyIHsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2UyX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5CdWlsZGVyLmNsYXNzKTsKICAgICAgICB9CgogICAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLm5ld0J1aWxkZXIoKQogICAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgICAgZGRfID0gMDsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZTJfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgYnVpbGQoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIodGhpcyk7CiAgICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgICAgb25CdWlsdCgpOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgcmVzdWx0KSB7CiAgICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICAgIHJlc3VsdC5kZF8gPSBkZF87CiAgICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKSB7CiAgICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpb3RoZXIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgICAgaWYgKG90aGVyLmhhc0RkKCkpIHsKICAgICAgICAgICAgc2V0RGQob3RoZXIuZ2V0RGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgICAgZGRfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgICAgcHJpdmF0ZSBpbnQgZGRfIDsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZCA9IDE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGQgZmllbGQgaXMgc2V0LgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZCgpIHsKICAgICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGQgPSAxOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBkZC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGludCBnZXREZCgpIHsKICAgICAgICAgIHJldHVybiBkZF87CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRkID0gMTs8L2NvZGU+CiAgICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZCB0byBzZXQuCiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERkKGludCB2YWx1ZSkgewoKICAgICAgICAgIGRkXyA9IHZhbHVlOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGQgPSAxOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZCgpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgIGRkXyA9IDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCgogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpCiAgICAgIH0KCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIHN0YXRpYyB7CiAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE5lc3RlZE1lc3NhZ2UyPgogICAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8TmVzdGVkTWVzc2FnZTI+KCkgewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgTmVzdGVkTWVzc2FnZTIgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOZXN0ZWRNZXNzYWdlMj4gcGFyc2VyKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE5lc3RlZE1lc3NhZ2UyPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgIH0KCiAgICBwdWJsaWMgaW50ZXJmYWNlIE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgYm9vbGVhbiBoYXNBKCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICAgKi8KICAgICAgaW50IGdldEEoKTsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIE9wdGlvbmFsR3JvdXAgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgICBPcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgICAvLyBVc2UgT3B0aW9uYWxHcm91cC5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgICBwcml2YXRlIE9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBPcHRpb25hbEdyb3VwKCkgewogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICByZXR1cm4gbmV3IE9wdGlvbmFsR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgQV9GSUVMRF9OVU1CRVIgPSAxNzsKICAgICAgcHJpdmF0ZSBpbnQgYV8gPSAwOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzQSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGEuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0QSgpIHsKICAgICAgICByZXR1cm4gYV87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigxNywgYV8pOwogICAgICAgIH0KICAgICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgICBzaXplID0gMDsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxNywgYV8pOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgICAgcmV0dXJuIHNpemU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXApKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgICAgfQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXApIG9iajsKCiAgICAgICAgaWYgKGhhc0EoKSAhPSBvdGhlci5oYXNBKCkpIHJldHVybiBmYWxzZTsKICAgICAgICBpZiAoaGFzQSgpKSB7CiAgICAgICAgICBpZiAoZ2V0QSgpCiAgICAgICAgICAgICAgIT0gb3RoZXIuZ2V0QSgpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgICB9CiAgICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgICBpZiAoaGFzQSgpKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBBX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEEoKTsKICAgICAgICB9CiAgICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgICAgcmV0dXJuIGhhc2g7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHByb3RvdHlwZSkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cH0KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwKQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX09wdGlvbmFsR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgIH0KCiAgICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5uZXdCdWlsZGVyKCkKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgIGFfID0gMDsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBidWlsZCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwKHRoaXMpOwogICAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICAgIG9uQnVpbHQoKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgcmVzdWx0KSB7CiAgICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICAgIHJlc3VsdC5hXyA9IGFfOwogICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwKSB7CiAgICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cClvdGhlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgICAgaWYgKG90aGVyLmhhc0EoKSkgewogICAgICAgICAgICBzZXRBKG90aGVyLmdldEEoKSk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDEzNjogewogICAgICAgICAgICAgICAgICBhXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDEzNgogICAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgICAgcHJpdmF0ZSBpbnQgYV8gOwogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzQSgpIHsKICAgICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgICAgICByZXR1cm4gYV87CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBhIHRvIHNldC4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0QShpbnQgdmFsdWUpIHsKCiAgICAgICAgICBhXyA9IHZhbHVlOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJBKCkgewogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgYV8gPSAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgoKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgIH0KCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBERUZBVUxUX0lOU1RBTkNFOwogICAgICBzdGF0aWMgewogICAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cD4KICAgICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPE9wdGlvbmFsR3JvdXA+KCkgewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgT3B0aW9uYWxHcm91cCBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE9wdGlvbmFsR3JvdXA+IHBhcnNlcigpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxPcHRpb25hbEdyb3VwPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICB9CgogICAgfQoKICAgIHB1YmxpYyBpbnRlcmZhY2UgUmVwZWF0ZWRHcm91cE9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBib29sZWFuIGhhc0EoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGEuCiAgICAgICAqLwogICAgICBpbnQgZ2V0QSgpOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXB9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgUmVwZWF0ZWRHcm91cCBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKQogICAgICAgIFJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAgIC8vIFVzZSBSZXBlYXRlZEdyb3VwLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgIHByaXZhdGUgUmVwZWF0ZWRHcm91cChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgfQogICAgICBwcml2YXRlIFJlcGVhdGVkR3JvdXAoKSB7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICAgIHJldHVybiBuZXcgUmVwZWF0ZWRHcm91cCgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfUmVwZWF0ZWRHcm91cF9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9SZXBlYXRlZEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBBX0ZJRUxEX05VTUJFUiA9IDQ3OwogICAgICBwcml2YXRlIGludCBhXyA9IDA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRBKCkgewogICAgICAgIHJldHVybiBhXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIG91dHB1dC53cml0ZUludDMyKDQ3LCBhXyk7CiAgICAgICAgfQogICAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICAgIHNpemUgPSAwOwogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDQ3LCBhXyk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgICByZXR1cm4gc2l6ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCkpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgICB9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCkgb2JqOwoKICAgICAgICBpZiAoaGFzQSgpICE9IG90aGVyLmhhc0EoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICAgIGlmIChnZXRBKCkKICAgICAgICAgICAgICAhPSBvdGhlci5nZXRBKCkpIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICAgIH0KICAgICAgICBpbnQgaGFzaCA9IDQxOwogICAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEFfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0QSgpOwogICAgICAgIH0KICAgICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgICByZXR1cm4gaGFzaDsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgcHJvdG90eXBlKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXApCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgewogICAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfUmVwZWF0ZWRHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfUmVwZWF0ZWRHcm91cF9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwLm5ld0J1aWxkZXIoKQogICAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgICAgYV8gPSAwOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIGJ1aWxkKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAodGhpcyk7CiAgICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgICAgb25CdWlsdCgpOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCByZXN1bHQpIHsKICAgICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgcmVzdWx0LmFfID0gYV87CiAgICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXApIHsKICAgICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwKW90aGVyKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgICBpZiAob3RoZXIuaGFzQSgpKSB7CiAgICAgICAgICAgIHNldEEob3RoZXIuZ2V0QSgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgMzc2OiB7CiAgICAgICAgICAgICAgICAgIGFfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgMzc2CiAgICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgICBwcml2YXRlIGludCBhXyA7CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhlIGEuCiAgICAgICAgICovCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgZ2V0QSgpIHsKICAgICAgICAgIHJldHVybiBhXzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGEgdG8gc2V0LgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRBKGludCB2YWx1ZSkgewoKICAgICAgICAgIGFfID0gdmFsdWU7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckEoKSB7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgICBhXyA9IDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCgogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgfQoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIHN0YXRpYyB7CiAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXAgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEdyb3VwPgogICAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UmVwZWF0ZWRHcm91cD4oKSB7CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBSZXBlYXRlZEdyb3VwIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UmVwZWF0ZWRHcm91cD4gcGFyc2VyKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlcGVhdGVkR3JvdXA+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+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAxMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2UgPSAxODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbE5lc3RlZE1lc3NhZ2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0ZPUkVJR05fTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAxOTsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxGb3JlaWduTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDIwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9mb3JlaWduX21lc3NhZ2UgPSAxOTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZvcmVpZ25NZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxGb3JlaWduTWVzc2FnZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxGb3JlaWduTWVzc2FnZV87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfSU1QT1JUX01FU1NBR0VfRklFTERfTlVNQkVSID0gMjA7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV87CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW1wb3J0TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW1wb3J0TWVzc2FnZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwNDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbXBvcnRNZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEltcG9ydE1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEltcG9ydE1lc3NhZ2VfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX05FU1RFRF9FTlVNX0ZJRUxEX05VTUJFUiA9IDIxOwogICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxOZXN0ZWRFbnVtXyA9IDE7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gb3B0aW9uYWxfbmVzdGVkX2VudW0gPSAyMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsTmVzdGVkRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxOZXN0ZWRFbnVtKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDA4MDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gb3B0aW9uYWxfbmVzdGVkX2VudW0gPSAyMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbE5lc3RlZEVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBnZXRPcHRpb25hbE5lc3RlZEVudW0oKSB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uZm9yTnVtYmVyKG9wdGlvbmFsTmVzdGVkRW51bV8pOwogICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uRk9PIDogcmVzdWx0OwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0ZPUkVJR05fRU5VTV9GSUVMRF9OVU1CRVIgPSAyMjsKICAgIHByaXZhdGUgaW50IG9wdGlvbmFsRm9yZWlnbkVudW1fID0gNDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9mb3JlaWduX2VudW0gPSAyMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRm9yZWlnbkVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsRm9yZWlnbkVudW0oKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMTAwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9mb3JlaWduX2VudW0gPSAyMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZvcmVpZ25FbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgZ2V0T3B0aW9uYWxGb3JlaWduRW51bSgpIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIob3B0aW9uYWxGb3JlaWduRW51bV8pOwogICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuRk9SRUlHTl9MSVRFX0ZPTyA6IHJlc3VsdDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9JTVBPUlRfRU5VTV9GSUVMRF9OVU1CRVIgPSAyMzsKICAgIHByaXZhdGUgaW50IG9wdGlvbmFsSW1wb3J0RW51bV8gPSA3OwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIG9wdGlvbmFsX2ltcG9ydF9lbnVtID0gMjM7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEltcG9ydEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW1wb3J0RW51bSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAyMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIG9wdGlvbmFsX2ltcG9ydF9lbnVtID0gMjM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbXBvcnRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSBnZXRPcHRpb25hbEltcG9ydEVudW0oKSB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLmZvck51bWJlcihvcHRpb25hbEltcG9ydEVudW1fKTsKICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuSU1QT1JUX0xJVEVfRk9PIDogcmVzdWx0OwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NUUklOR19QSUVDRV9GSUVMRF9OVU1CRVIgPSAyNDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSB2b2xhdGlsZSBqYXZhLmxhbmcuT2JqZWN0IG9wdGlvbmFsU3RyaW5nUGllY2VfID0gIiI7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTdHJpbmdQaWVjZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nUGllY2UoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwNDAwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZ19waWVjZSA9IDI0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTdHJpbmdQaWVjZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T3B0aW9uYWxTdHJpbmdQaWVjZSgpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ1BpZWNlXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZ1BpZWNlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T3B0aW9uYWxTdHJpbmdQaWVjZUJ5dGVzKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IG9wdGlvbmFsU3RyaW5nUGllY2VfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9IGI7CiAgICAgICAgcmV0dXJuIGI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0NPUkRfRklFTERfTlVNQkVSID0gMjU7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgdm9sYXRpbGUgamF2YS5sYW5nLk9iamVjdCBvcHRpb25hbENvcmRfID0gIiI7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9jb3JkID0gMjUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbENvcmQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbENvcmQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwODAwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX2NvcmQgPSAyNSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbENvcmQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE9wdGlvbmFsQ29yZCgpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbENvcmRfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgIG9wdGlvbmFsQ29yZF8gPSBzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gczsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbENvcmQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPcHRpb25hbENvcmRCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbENvcmRfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICBvcHRpb25hbENvcmRfID0gYjsKICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfUFVCTElDX0lNUE9SVF9NRVNTQUdFX0ZJRUxEX05VTUJFUiA9IDI2OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfOwogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMTAwMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9MQVpZX01FU1NBR0VfRklFTERfTlVNQkVSID0gMjc7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbExhenlNZXNzYWdlXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxMYXp5TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsTGF6eU1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAyMDAwMDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTGF6eU1lc3NhZ2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZSgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsTGF6eU1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbExhenlNZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbExhenlNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxMYXp5TWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsTGF6eU1lc3NhZ2VfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1VOVkVSSUZJRURfTEFaWV9NRVNTQUdFX0ZJRUxEX05VTUJFUiA9IDI4OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDQwMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZV87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfSU5UMzJfRklFTERfTlVNQkVSID0gMzE7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkSW50MzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFJlcGVhdGVkCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDMxOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRSZXBlYXRlZEludDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogUmVwZWF0ZWQKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMzE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbnQzMi4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBSZXBlYXRlZAogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAzMTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50MzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lOVDY0X0ZJRUxEX05VTUJFUiA9IDMyOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcmVwZWF0ZWRJbnQ2NF8gPQogICAgICAgIGVtcHR5TG9uZ0xpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcmVwZWF0ZWRfaW50NjQgPSAzMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgZ2V0UmVwZWF0ZWRJbnQ2NExpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDY0XzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcmVwZWF0ZWRfaW50NjQgPSAzMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEludDY0LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50NjRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcmVwZWF0ZWRfaW50NjQgPSAzMjs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgbG9uZyBnZXRSZXBlYXRlZEludDY0KGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfVUlOVDMyX0ZJRUxEX05VTUJFUiA9IDMzOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZFVpbnQzMl8gPQogICAgICAgIGVtcHR5SW50TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcmVwZWF0ZWRfdWludDMyID0gMzM7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRVaW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRSZXBlYXRlZFVpbnQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZFVpbnQzMl87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiByZXBlYXRlZF91aW50MzIgPSAzMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFVpbnQzMi4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZFVpbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRVaW50MzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHJlcGVhdGVkX3VpbnQzMiA9IDMzOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRVaW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkVWludDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRVaW50MzJfLmdldEludChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfVUlOVDY0X0ZJRUxEX05VTUJFUiA9IDM0OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcmVwZWF0ZWRVaW50NjRfID0KICAgICAgICBlbXB0eUxvbmdMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCByZXBlYXRlZF91aW50NjQgPSAzNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFVpbnQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgIGdldFJlcGVhdGVkVWludDY0TGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkVWludDY0XzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHJlcGVhdGVkX3VpbnQ2NCA9IDM0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkVWludDY0LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkVWludDY0Q291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZFVpbnQ2NF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcmVwZWF0ZWRfdWludDY0ID0gMzQ7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFVpbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBsb25nIGdldFJlcGVhdGVkVWludDY0KGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRVaW50NjRfLmdldExvbmcoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1NJTlQzMl9GSUVMRF9OVU1CRVIgPSAzNTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRTaW50MzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHJlcGVhdGVkX3NpbnQzMiA9IDM1OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkU2ludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UmVwZWF0ZWRTaW50MzJMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTaW50MzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcmVwZWF0ZWRfc2ludDMyID0gMzU7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTaW50MzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTaW50MzJDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ludDMyXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiByZXBlYXRlZF9zaW50MzIgPSAzNTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU2ludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZFNpbnQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1NJTlQ2NF9GSUVMRF9OVU1CRVIgPSAzNjsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHJlcGVhdGVkU2ludDY0XyA9CiAgICAgICAgZW1wdHlMb25nTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcmVwZWF0ZWRfc2ludDY0ID0gMzY7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTaW50NjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICBnZXRSZXBlYXRlZFNpbnQ2NExpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZFNpbnQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCByZXBlYXRlZF9zaW50NjQgPSAzNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFNpbnQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZFNpbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTaW50NjRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHJlcGVhdGVkX3NpbnQ2NCA9IDM2OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgbG9uZyBnZXRSZXBlYXRlZFNpbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ludDY0Xy5nZXRMb25nKGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GSVhFRDMyX0ZJRUxEX05VTUJFUiA9IDM3OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEZpeGVkMzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMzc7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRGaXhlZDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDM3OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRml4ZWQzMi4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAzNzs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0ZJWEVENjRfRklFTERfTlVNQkVSID0gMzg7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCByZXBlYXRlZEZpeGVkNjRfID0KICAgICAgICBlbXB0eUxvbmdMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcmVwZWF0ZWRfZml4ZWQ2NCA9IDM4OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgIGdldFJlcGVhdGVkRml4ZWQ2NExpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkNjRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHJlcGVhdGVkX2ZpeGVkNjQgPSAzODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkNjQuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkNjRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCByZXBlYXRlZF9maXhlZDY0ID0gMzg7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkNjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgbG9uZyBnZXRSZXBlYXRlZEZpeGVkNjQoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkNjRfLmdldExvbmcoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1NGSVhFRDMyX0ZJRUxEX05VTUJFUiA9IDM5OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZFNmaXhlZDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHJlcGVhdGVkX3NmaXhlZDMyID0gMzk7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTZml4ZWQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFJlcGVhdGVkU2ZpeGVkMzJMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTZml4ZWQzMl87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHJlcGVhdGVkX3NmaXhlZDMyID0gMzk7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTZml4ZWQzMi4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZFNmaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZFNmaXhlZDMyXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHJlcGVhdGVkX3NmaXhlZDMyID0gMzk7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFNmaXhlZDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZFNmaXhlZDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTZml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TRklYRUQ2NF9GSUVMRF9OVU1CRVIgPSA0MDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHJlcGVhdGVkU2ZpeGVkNjRfID0KICAgICAgICBlbXB0eUxvbmdMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHJlcGVhdGVkX3NmaXhlZDY0ID0gNDA7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTZml4ZWQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgIGdldFJlcGVhdGVkU2ZpeGVkNjRMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTZml4ZWQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHJlcGVhdGVkX3NmaXhlZDY0ID0gNDA7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTZml4ZWQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZFNmaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZFNmaXhlZDY0Xy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHJlcGVhdGVkX3NmaXhlZDY0ID0gNDA7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFNmaXhlZDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGxvbmcgZ2V0UmVwZWF0ZWRTZml4ZWQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU2ZpeGVkNjRfLmdldExvbmcoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0ZMT0FUX0ZJRUxEX05VTUJFUiA9IDQxOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRmxvYXRMaXN0IHJlcGVhdGVkRmxvYXRfID0KICAgICAgICBlbXB0eUZsb2F0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCByZXBlYXRlZF9mbG9hdCA9IDQxOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRmxvYXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgZ2V0UmVwZWF0ZWRGbG9hdExpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZsb2F0XzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcmVwZWF0ZWRfZmxvYXQgPSA0MTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZsb2F0LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRmxvYXRDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRmxvYXRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcmVwZWF0ZWRfZmxvYXQgPSA0MTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRmxvYXQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgZmxvYXQgZ2V0UmVwZWF0ZWRGbG9hdChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRmxvYXRfLmdldEZsb2F0KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9ET1VCTEVfRklFTERfTlVNQkVSID0gNDI7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Eb3VibGVMaXN0IHJlcGVhdGVkRG91YmxlXyA9CiAgICAgICAgZW1wdHlEb3VibGVMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSByZXBlYXRlZF9kb3VibGUgPSA0Mjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZERvdWJsZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgZ2V0UmVwZWF0ZWREb3VibGVMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWREb3VibGVfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcmVwZWF0ZWRfZG91YmxlID0gNDI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWREb3VibGUuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWREb3VibGVDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRG91YmxlXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSByZXBlYXRlZF9kb3VibGUgPSA0Mjs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRG91YmxlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGRvdWJsZSBnZXRSZXBlYXRlZERvdWJsZShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRG91YmxlXy5nZXREb3VibGUoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0JPT0xfRklFTERfTlVNQkVSID0gNDM7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Cb29sZWFuTGlzdCByZXBlYXRlZEJvb2xfID0KICAgICAgICBlbXB0eUJvb2xlYW5MaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcmVwZWF0ZWRfYm9vbCA9IDQzOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkQm9vbC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgIGdldFJlcGVhdGVkQm9vbExpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEJvb2xfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHJlcGVhdGVkX2Jvb2wgPSA0Mzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEJvb2wuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRCb29sQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEJvb2xfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCByZXBlYXRlZF9ib29sID0gNDM7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEJvb2wgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgYm9vbGVhbiBnZXRSZXBlYXRlZEJvb2woaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEJvb2xfLmdldEJvb2xlYW4oaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1NUUklOR19GSUVMRF9OVU1CRVIgPSA0NDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QgcmVwZWF0ZWRTdHJpbmdfID0KICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFN0cmluZy4KICAgICAqLwogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xTdHJpbmdMaXN0CiAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nID0gNDQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRTdHJpbmcuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRTdHJpbmdDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmcgPSA0NDs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkU3RyaW5nIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0UmVwZWF0ZWRTdHJpbmcoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZFN0cmluZ18uZ2V0KGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZyA9IDQ0OzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHZhbHVlIHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZFN0cmluZyBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRSZXBlYXRlZFN0cmluZ0J5dGVzKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRTdHJpbmdfLmdldEJ5dGVTdHJpbmcoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0JZVEVTX0ZJRUxEX05VTUJFUiA9IDQ1OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuUHJvdG9idWZMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gcmVwZWF0ZWRCeXRlc18gPQogICAgICAgIGVtcHR5TGlzdChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY2xhc3MpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBieXRlcyByZXBlYXRlZF9ieXRlcyA9IDQ1OzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkQnl0ZXMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICAgICAgZ2V0UmVwZWF0ZWRCeXRlc0xpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEJ5dGVzXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEJ5dGVzLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkQnl0ZXNDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkQnl0ZXNfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYnl0ZXMgcmVwZWF0ZWRfYnl0ZXMgPSA0NTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkQnl0ZXMgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldFJlcGVhdGVkQnl0ZXMoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEJ5dGVzXy5nZXQoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVER1JPVVBfRklFTERfTlVNQkVSID0gNDY7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXRlZEdyb3VwPiByZXBlYXRlZEdyb3VwXzsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXA+IGdldFJlcGVhdGVkR3JvdXBMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSA0NiB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cE9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cE9yQnVpbGRlckxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRHcm91cENvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gNDYgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBnZXRSZXBlYXRlZEdyb3VwKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF8uZ2V0KGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDQ2IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRHcm91cE9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfLmdldChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfTkVTVEVEX01FU1NBR0VfRklFTERfTlVNQkVSID0gNDg7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZU9yQnVpbGRlckxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5nZXQoaW5kZXgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZU9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GT1JFSUdOX01FU1NBR0VfRklFTERfTlVNQkVSID0gNDk7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXzsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZU9yQnVpbGRlckxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZU9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmdldChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfSU1QT1JUX01FU1NBR0VfRklFTERfTlVNQkVSID0gNTA7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGU+IHJlcGVhdGVkSW1wb3J0TWVzc2FnZV87CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZT4gZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXI+IAogICAgICAgIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZU9yQnVpbGRlckxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLmdldChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfTkVTVEVEX0VOVU1fRklFTERfTlVNQkVSID0gNTE7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IHJlcGVhdGVkTmVzdGVkRW51bV87CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtPiByZXBlYXRlZE5lc3RlZEVudW1fY29udmVydGVyXyA9CiAgICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+KCkgewogICAgICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gY29udmVydChqYXZhLmxhbmcuSW50ZWdlciBmcm9tKSB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLmZvck51bWJlcihmcm9tKTsKICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5GT08gOiByZXN1bHQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9OwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWROZXN0ZWRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtPiBnZXRSZXBlYXRlZE5lc3RlZEVudW1MaXN0KCkgewogICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtPihyZXBlYXRlZE5lc3RlZEVudW1fLCByZXBlYXRlZE5lc3RlZEVudW1fY29udmVydGVyXyk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVwZWF0ZWRfbmVzdGVkX2VudW0gPSA1MTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZE5lc3RlZEVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWROZXN0ZWRFbnVtQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZEVudW1fLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWROZXN0ZWRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBnZXRSZXBlYXRlZE5lc3RlZEVudW0oaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZEVudW1fY29udmVydGVyXy5jb252ZXJ0KHJlcGVhdGVkTmVzdGVkRW51bV8uZ2V0KGluZGV4KSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRk9SRUlHTl9FTlVNX0ZJRUxEX05VTUJFUiA9IDUyOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiByZXBlYXRlZEZvcmVpZ25FbnVtXzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IHJlcGVhdGVkRm9yZWlnbkVudW1fY29udmVydGVyXyA9CiAgICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+KCkgewogICAgICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgY29udmVydChqYXZhLmxhbmcuSW50ZWdlciBmcm9tKSB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcihmcm9tKTsKICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5GT1JFSUdOX0xJVEVfRk9PIDogcmVzdWx0OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZvcmVpZ25FbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPiBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtTGlzdCgpIHsKICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZT4ocmVwZWF0ZWRGb3JlaWduRW51bV8sIHJlcGVhdGVkRm9yZWlnbkVudW1fY29udmVydGVyXyk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9lbnVtID0gNTI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGb3JlaWduRW51bS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25FbnVtXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9lbnVtID0gNTI7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZvcmVpZ25FbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduRW51bV9jb252ZXJ0ZXJfLmNvbnZlcnQocmVwZWF0ZWRGb3JlaWduRW51bV8uZ2V0KGluZGV4KSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfSU1QT1JUX0VOVU1fRklFTERfTlVNQkVSID0gNTM7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IHJlcGVhdGVkSW1wb3J0RW51bV87CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGU+IHJlcGVhdGVkSW1wb3J0RW51bV9jb252ZXJ0ZXJfID0KICAgICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlPigpIHsKICAgICAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgY29udmVydChqYXZhLmxhbmcuSW50ZWdlciBmcm9tKSB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5mb3JOdW1iZXIoZnJvbSk7CiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5JTVBPUlRfTElURV9GT08gOiByZXN1bHQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9OwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbXBvcnRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGU+IGdldFJlcGVhdGVkSW1wb3J0RW51bUxpc3QoKSB7CiAgICAgIHJldHVybiBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5MaXN0QWRhcHRlcjwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4ocmVwZWF0ZWRJbXBvcnRFbnVtXywgcmVwZWF0ZWRJbXBvcnRFbnVtX2NvbnZlcnRlcl8pOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbXBvcnRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW1wb3J0RW51bUNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRFbnVtXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW1wb3J0RW51bSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSBnZXRSZXBlYXRlZEltcG9ydEVudW0oaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydEVudW1fY29udmVydGVyXy5jb252ZXJ0KHJlcGVhdGVkSW1wb3J0RW51bV8uZ2V0KGluZGV4KSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfU1RSSU5HX1BJRUNFX0ZJRUxEX05VTUJFUiA9IDU0OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdCByZXBlYXRlZFN0cmluZ1BpZWNlXyA9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZFN0cmluZ1BpZWNlLgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Qcm90b2NvbFN0cmluZ0xpc3QKICAgICAgICBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nUGllY2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFN0cmluZ1BpZWNlLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkU3RyaW5nUGllY2VDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nUGllY2VfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nUGllY2VfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHZhbHVlIHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldFJlcGVhdGVkU3RyaW5nUGllY2VCeXRlcyhpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nUGllY2VfLmdldEJ5dGVTdHJpbmcoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0NPUkRfRklFTERfTlVNQkVSID0gNTU7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0IHJlcGVhdGVkQ29yZF8gPQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdC5lbXB0eUxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX2NvcmQgPSA1NSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZENvcmQuCiAgICAgKi8KICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sU3RyaW5nTGlzdAogICAgICAgIGdldFJlcGVhdGVkQ29yZExpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZENvcmRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkQ29yZC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZENvcmRDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkQ29yZF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRDb3JkIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0UmVwZWF0ZWRDb3JkKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRDb3JkXy5nZXQoaW5kZXgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHZhbHVlIHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZENvcmQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0UmVwZWF0ZWRDb3JkQnl0ZXMoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZENvcmRfLmdldEJ5dGVTdHJpbmcoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0xBWllfTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSA1NzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IHJlcGVhdGVkTGF6eU1lc3NhZ2VfOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiBnZXRSZXBlYXRlZExhenlNZXNzYWdlTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZU9yQnVpbGRlckxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZExhenlNZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRSZXBlYXRlZExhenlNZXNzYWdlQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZExhenlNZXNzYWdlXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmdldChpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZU9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmdldChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9JTlQzMl9GSUVMRF9OVU1CRVIgPSA2MTsKICAgIHByaXZhdGUgaW50IGRlZmF1bHRJbnQzMl8gPSA0MTsKICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFNpbmd1bGFyIHdpdGggZGVmYXVsdHMKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlZmF1bHRfaW50MzIgPSA2MSBbZGVmYXVsdCA9IDQxXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRJbnQzMigpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDgwMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogU2luZ3VsYXIgd2l0aCBkZWZhdWx0cwogICAgICogPC9wcmU+CiAgICAgKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVmYXVsdF9pbnQzMiA9IDYxIFtkZWZhdWx0ID0gNDFdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRJbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXREZWZhdWx0SW50MzIoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0SW50MzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfSU5UNjRfRklFTERfTlVNQkVSID0gNjI7CiAgICBwcml2YXRlIGxvbmcgZGVmYXVsdEludDY0XyA9IDQyTDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgZGVmYXVsdF9pbnQ2NCA9IDYyIFtkZWZhdWx0ID0gNDJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEludDY0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEludDY0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgxMDAwMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGRlZmF1bHRfaW50NjQgPSA2MiBbZGVmYXVsdCA9IDQyXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0SW50NjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldERlZmF1bHRJbnQ2NCgpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRJbnQ2NF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9VSU5UMzJfRklFTERfTlVNQkVSID0gNjM7CiAgICBwcml2YXRlIGludCBkZWZhdWx0VWludDMyXyA9IDQzOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgZGVmYXVsdF91aW50MzIgPSA2MyBbZGVmYXVsdCA9IDQzXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0VWludDMyKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgyMDAwMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBkZWZhdWx0X3VpbnQzMiA9IDYzIFtkZWZhdWx0ID0gNDNdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRVaW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0RGVmYXVsdFVpbnQzMigpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRVaW50MzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfVUlOVDY0X0ZJRUxEX05VTUJFUiA9IDY0OwogICAgcHJpdmF0ZSBsb25nIGRlZmF1bHRVaW50NjRfID0gNDRMOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50NjQgZGVmYXVsdF91aW50NjQgPSA2NCBbZGVmYXVsdCA9IDQ0XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRVaW50NjQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0VWludDY0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHg0MDAwMDAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQ2NCBkZWZhdWx0X3VpbnQ2NCA9IDY0IFtkZWZhdWx0ID0gNDRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRVaW50NjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldERlZmF1bHRVaW50NjQoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0VWludDY0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1NJTlQzMl9GSUVMRF9OVU1CRVIgPSA2NTsKICAgIHByaXZhdGUgaW50IGRlZmF1bHRTaW50MzJfID0gLTQ1OwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgZGVmYXVsdF9zaW50MzIgPSA2NSBbZGVmYXVsdCA9IC00NV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U2ludDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdFNpbnQzMigpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4ODAwMDAwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgZGVmYXVsdF9zaW50MzIgPSA2NSBbZGVmYXVsdCA9IC00NV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdFNpbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXREZWZhdWx0U2ludDMyKCkgewogICAgICByZXR1cm4gZGVmYXVsdFNpbnQzMl87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9TSU5UNjRfRklFTERfTlVNQkVSID0gNjY7CiAgICBwcml2YXRlIGxvbmcgZGVmYXVsdFNpbnQ2NF8gPSA0Nkw7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBkZWZhdWx0X3NpbnQ2NCA9IDY2IFtkZWZhdWx0ID0gNDZdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFNpbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTaW50NjQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IGRlZmF1bHRfc2ludDY0ID0gNjYgW2RlZmF1bHQgPSA0Nl07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdFNpbnQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0RGVmYXVsdFNpbnQ2NCgpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRTaW50NjRfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfRklYRUQzMl9GSUVMRF9OVU1CRVIgPSA2NzsKICAgIHByaXZhdGUgaW50IGRlZmF1bHRGaXhlZDMyXyA9IDQ3OwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIGRlZmF1bHRfZml4ZWQzMiA9IDY3IFtkZWZhdWx0ID0gNDddOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Rml4ZWQzMigpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIGRlZmF1bHRfZml4ZWQzMiA9IDY3IFtkZWZhdWx0ID0gNDddOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGaXhlZDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldERlZmF1bHRGaXhlZDMyKCkgewogICAgICByZXR1cm4gZGVmYXVsdEZpeGVkMzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfRklYRUQ2NF9GSUVMRF9OVU1CRVIgPSA2ODsKICAgIHByaXZhdGUgbG9uZyBkZWZhdWx0Rml4ZWQ2NF8gPSA0OEw7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgZGVmYXVsdF9maXhlZDY0ID0gNjggW2RlZmF1bHQgPSA0OF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Rml4ZWQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRGaXhlZDY0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwMDAwNCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgZGVmYXVsdF9maXhlZDY0ID0gNjggW2RlZmF1bHQgPSA0OF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdEZpeGVkNjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldERlZmF1bHRGaXhlZDY0KCkgewogICAgICByZXR1cm4gZGVmYXVsdEZpeGVkNjRfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU0ZJWEVEMzJfRklFTERfTlVNQkVSID0gNjk7CiAgICBwcml2YXRlIGludCBkZWZhdWx0U2ZpeGVkMzJfID0gNDk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIGRlZmF1bHRfc2ZpeGVkMzIgPSA2OSBbZGVmYXVsdCA9IDQ5XTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTZml4ZWQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTZml4ZWQzMigpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDAwMDgpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQzMiBkZWZhdWx0X3NmaXhlZDMyID0gNjkgW2RlZmF1bHQgPSA0OV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdFNmaXhlZDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldERlZmF1bHRTZml4ZWQzMigpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRTZml4ZWQzMl87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9TRklYRUQ2NF9GSUVMRF9OVU1CRVIgPSA3MDsKICAgIHByaXZhdGUgbG9uZyBkZWZhdWx0U2ZpeGVkNjRfID0gLTUwTDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgZGVmYXVsdF9zZml4ZWQ2NCA9IDcwIFtkZWZhdWx0ID0gLTUwXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTZml4ZWQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTZml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDAwMTApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBkZWZhdWx0X3NmaXhlZDY0ID0gNzAgW2RlZmF1bHQgPSAtNTBdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTZml4ZWQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0RGVmYXVsdFNmaXhlZDY0KCkgewogICAgICByZXR1cm4gZGVmYXVsdFNmaXhlZDY0XzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0ZMT0FUX0ZJRUxEX05VTUJFUiA9IDcxOwogICAgcHJpdmF0ZSBmbG9hdCBkZWZhdWx0RmxvYXRfID0gNTEuNUY7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IGRlZmF1bHRfZmxvYXQgPSA3MSBbZGVmYXVsdCA9IDUxLjVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZsb2F0IGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEZsb2F0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwMDAyMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IGRlZmF1bHRfZmxvYXQgPSA3MSBbZGVmYXVsdCA9IDUxLjVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGbG9hdC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZsb2F0IGdldERlZmF1bHRGbG9hdCgpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRGbG9hdF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9ET1VCTEVfRklFTERfTlVNQkVSID0gNzI7CiAgICBwcml2YXRlIGRvdWJsZSBkZWZhdWx0RG91YmxlXyA9IDUyMDAwRDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIGRlZmF1bHRfZG91YmxlID0gNzIgW2RlZmF1bHQgPSA1MjAwMF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0RG91YmxlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdERvdWJsZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDAwNDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgZGVmYXVsdF9kb3VibGUgPSA3MiBbZGVmYXVsdCA9IDUyMDAwXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0RG91YmxlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZG91YmxlIGdldERlZmF1bHREb3VibGUoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0RG91YmxlXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0JPT0xfRklFTERfTlVNQkVSID0gNzM7CiAgICBwcml2YXRlIGJvb2xlYW4gZGVmYXVsdEJvb2xfID0gdHJ1ZTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBkZWZhdWx0X2Jvb2wgPSA3MyBbZGVmYXVsdCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEJvb2wgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Qm9vbCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDAwODApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBib29sIGRlZmF1bHRfYm9vbCA9IDczIFtkZWZhdWx0ID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdEJvb2wuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGdldERlZmF1bHRCb29sKCkgewogICAgICByZXR1cm4gZGVmYXVsdEJvb2xfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU1RSSU5HX0ZJRUxEX05VTUJFUiA9IDc0OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIHZvbGF0aWxlIGphdmEubGFuZy5PYmplY3QgZGVmYXVsdFN0cmluZ18gPSAiaGVsbG8iOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmcgPSA3NCBbZGVmYXVsdCA9ICJoZWxsbyJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFN0cmluZyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTdHJpbmcoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwMTAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U3RyaW5nLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXREZWZhdWx0U3RyaW5nKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlZmF1bHRTdHJpbmdfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgIGRlZmF1bHRTdHJpbmdfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nID0gNzQgW2RlZmF1bHQgPSAiaGVsbG8iXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVmYXVsdFN0cmluZy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldERlZmF1bHRTdHJpbmdCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0U3RyaW5nXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgZGVmYXVsdFN0cmluZ18gPSBiOwogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0JZVEVTX0ZJRUxEX05VTUJFUiA9IDc1OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGVmYXVsdEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoIndvcmxkIik7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIGRlZmF1bHRfYnl0ZXMgPSA3NSBbZGVmYXVsdCA9ICJ3b3JsZCJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEJ5dGVzKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwMDIwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIGRlZmF1bHRfYnl0ZXMgPSA3NSBbZGVmYXVsdCA9ICJ3b3JsZCJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRCeXRlcy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXREZWZhdWx0Qnl0ZXMoKSB7CiAgICAgIHJldHVybiBkZWZhdWx0Qnl0ZXNfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfTkVTVEVEX0VOVU1fRklFTERfTlVNQkVSID0gODE7CiAgICBwcml2YXRlIGludCBkZWZhdWx0TmVzdGVkRW51bV8gPSAyOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGRlZmF1bHRfbmVzdGVkX2VudW0gPSA4MSBbZGVmYXVsdCA9IEJBUl07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0TmVzdGVkRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdE5lc3RlZEVudW0oKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwMDAwNDAwKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBkZWZhdWx0X25lc3RlZF9lbnVtID0gODEgW2RlZmF1bHQgPSBCQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHROZXN0ZWRFbnVtLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gZ2V0RGVmYXVsdE5lc3RlZEVudW0oKSB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uZm9yTnVtYmVyKGRlZmF1bHROZXN0ZWRFbnVtXyk7CiAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5CQVIgOiByZXN1bHQ7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9GT1JFSUdOX0VOVU1fRklFTERfTlVNQkVSID0gODI7CiAgICBwcml2YXRlIGludCBkZWZhdWx0Rm9yZWlnbkVudW1fID0gNTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBkZWZhdWx0X2ZvcmVpZ25fZW51bSA9IDgyIFtkZWZhdWx0ID0gRk9SRUlHTl9MSVRFX0JBUl07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Rm9yZWlnbkVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRGb3JlaWduRW51bSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDA4MDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIGRlZmF1bHRfZm9yZWlnbl9lbnVtID0gODIgW2RlZmF1bHQgPSBGT1JFSUdOX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Rm9yZWlnbkVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXREZWZhdWx0Rm9yZWlnbkVudW0oKSB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKGRlZmF1bHRGb3JlaWduRW51bV8pOwogICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuRk9SRUlHTl9MSVRFX0JBUiA6IHJlc3VsdDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0lNUE9SVF9FTlVNX0ZJRUxEX05VTUJFUiA9IDgzOwogICAgcHJpdmF0ZSBpbnQgZGVmYXVsdEltcG9ydEVudW1fID0gODsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBkZWZhdWx0X2ltcG9ydF9lbnVtID0gODMgW2RlZmF1bHQgPSBJTVBPUlRfTElURV9CQVJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEltcG9ydEVudW0gZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRJbXBvcnRFbnVtKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwMTAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgZGVmYXVsdF9pbXBvcnRfZW51bSA9IDgzIFtkZWZhdWx0ID0gSU1QT1JUX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0SW1wb3J0RW51bS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0RGVmYXVsdEltcG9ydEVudW0oKSB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLmZvck51bWJlcihkZWZhdWx0SW1wb3J0RW51bV8pOwogICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5JTVBPUlRfTElURV9CQVIgOiByZXN1bHQ7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSID0gODQ7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgdm9sYXRpbGUgamF2YS5sYW5nLk9iamVjdCBkZWZhdWx0U3RyaW5nUGllY2VfID0gImFiYyI7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTdHJpbmdQaWVjZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTdHJpbmdQaWVjZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDIwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmdfcGllY2UgPSA4NCBbZGVmYXVsdCA9ICJhYmMiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVmYXVsdFN0cmluZ1BpZWNlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXREZWZhdWx0U3RyaW5nUGllY2UoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVmYXVsdFN0cmluZ1BpZWNlXzsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfc3RyaW5nX3BpZWNlID0gODQgW2RlZmF1bHQgPSAiYWJjIiwgY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBkZWZhdWx0U3RyaW5nUGllY2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXREZWZhdWx0U3RyaW5nUGllY2VCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0U3RyaW5nUGllY2VfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gYjsKICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9DT1JEX0ZJRUxEX05VTUJFUiA9IDg1OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIHZvbGF0aWxlIGphdmEubGFuZy5PYmplY3QgZGVmYXVsdENvcmRfID0gIjEyMyI7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X2NvcmQgPSA4NSBbZGVmYXVsdCA9ICIxMjMiLCBjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdENvcmQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Q29yZCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAwMDQwMDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9jb3JkID0gODUgW2RlZmF1bHQgPSAiMTIzIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Q29yZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdENvcmQoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVmYXVsdENvcmRfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgIGRlZmF1bHRDb3JkXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X2NvcmQgPSA4NSBbZGVmYXVsdCA9ICIxMjMiLCBjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBkZWZhdWx0Q29yZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldERlZmF1bHRDb3JkQnl0ZXMoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVmYXVsdENvcmRfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICBkZWZhdWx0Q29yZF8gPSBiOwogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9VSU5UMzJfRklFTERfTlVNQkVSID0gMTExOwogICAgLyoqCiAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gMTExOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlVpbnQzMigpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxMTE7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSAxMTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZVaW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0T25lb2ZVaW50MzIoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTExKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfTkVTVEVEX01FU1NBR0VfRklFTERfTlVNQkVSID0gMTEyOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX25lc3RlZF9tZXNzYWdlID0gMTEyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZOZXN0ZWRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZOZXN0ZWRNZXNzYWdlKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDExMjsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZk5lc3RlZE1lc3NhZ2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMikgewogICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMikgewogICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9TVFJJTkdfRklFTERfTlVNQkVSID0gMTEzOwogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlN0cmluZygpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxMTM7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAxMTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE9uZW9mU3RyaW5nKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMykgewogICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gCiAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSAmJiAob25lb2ZGaWVsZENhc2VfID09IDExMykpIHsKICAgICAgICAgIG9uZW9mRmllbGRfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDExMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPbmVvZlN0cmluZ0J5dGVzKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMykgewogICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IGI7CiAgICAgICAgfQogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9CWVRFU19GSUVMRF9OVU1CRVIgPSAxMTQ7CiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gMTE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mQnl0ZXMoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTE0OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDExNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXMoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE0KSB7CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfTEFaWV9ORVNURURfTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAxMTU7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX2xhenlfbmVzdGVkX21lc3NhZ2UgPSAxMTUgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX2xhenlfbmVzdGVkX21lc3NhZ2UgPSAxMTUgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUpIHsKICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfTkVTVEVEX01FU1NBR0UyX0ZJRUxEX05VTUJFUiA9IDExNzsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZOZXN0ZWRNZXNzYWdlMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mTmVzdGVkTWVzc2FnZTIoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZOZXN0ZWRNZXNzYWdlMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlMigpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTcpIHsKICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTJPckJ1aWxkZXIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlMk9yQnVpbGRlcigpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTcpIHsKICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUNFUFRJVkVMWV9OQU1FRF9MSVNUX0ZJRUxEX05VTUJFUiA9IDExNjsKICAgIHByaXZhdGUgaW50IGRlY2VwdGl2ZWx5TmFtZWRMaXN0XyA9IDA7CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBUZXN0cyB0b1N0cmluZyBmb3Igbm9uLXJlcGVhdGVkIGZpZWxkcyB3aXRoIGEgbGlzdCBzdWZmaXgKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlY2VwdGl2ZWx5X25hbWVkX2xpc3QgPSAxMTY7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0RlY2VwdGl2ZWx5TmFtZWRMaXN0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDAwODAwMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBUZXN0cyB0b1N0cmluZyBmb3Igbm9uLXJlcGVhdGVkIGZpZWxkcyB3aXRoIGEgbGlzdCBzdWZmaXgKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlY2VwdGl2ZWx5X25hbWVkX2xpc3QgPSAxMTY7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZGVjZXB0aXZlbHlOYW1lZExpc3QuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0RGVjZXB0aXZlbHlOYW1lZExpc3QoKSB7CiAgICAgIHJldHVybiBkZWNlcHRpdmVseU5hbWVkTGlzdF87CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigxLCBvcHRpb25hbEludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50NjQoMiwgb3B0aW9uYWxJbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMigzLCBvcHRpb25hbFVpbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQ2NCg0LCBvcHRpb25hbFVpbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVNJbnQzMig1LCBvcHRpb25hbFNpbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDIwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVNJbnQ2NCg2LCBvcHRpb25hbFNpbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUZpeGVkMzIoNywgb3B0aW9uYWxGaXhlZDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRml4ZWQ2NCg4LCBvcHRpb25hbEZpeGVkNjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVTRml4ZWQzMig5LCBvcHRpb25hbFNmaXhlZDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAyMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlU0ZpeGVkNjQoMTAsIG9wdGlvbmFsU2ZpeGVkNjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDQwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVGbG9hdCgxMSwgb3B0aW9uYWxGbG9hdF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwODAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZURvdWJsZSgxMiwgb3B0aW9uYWxEb3VibGVfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVCb29sKDEzLCBvcHRpb25hbEJvb2xfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDE0LCBvcHRpb25hbFN0cmluZ18pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDA0MDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUJ5dGVzKDE1LCBvcHRpb25hbEJ5dGVzXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDgwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlR3JvdXAoMTYsIGdldE9wdGlvbmFsR3JvdXAoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMTAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxOCwgZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDIwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMTksIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwNDAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgyMCwgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDgwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oMjEsIG9wdGlvbmFsTmVzdGVkRW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMTAwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oMjIsIG9wdGlvbmFsRm9yZWlnbkVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDIwMDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtKDIzLCBvcHRpb25hbEltcG9ydEVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDQwMDAwMCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDI0LCBvcHRpb25hbFN0cmluZ1BpZWNlXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDA4MDAwMDApICE9IDApKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMud3JpdGVTdHJpbmcob3V0cHV0LCAyNSwgb3B0aW9uYWxDb3JkXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDEwMDAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgyNiwgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAyMDAwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMjcsIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDQwMDAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgyOCwgZ2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDMxLCByZXBlYXRlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQ2NCgzMiwgcmVwZWF0ZWRJbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFVpbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzIoMzMsIHJlcGVhdGVkVWludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRVaW50NjRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDY0KDM0LCByZXBlYXRlZFVpbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFNpbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVTSW50MzIoMzUsIHJlcGVhdGVkU2ludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRTaW50NjRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlU0ludDY0KDM2LCByZXBlYXRlZFNpbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRml4ZWQzMigzNywgcmVwZWF0ZWRGaXhlZDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRGaXhlZDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUZpeGVkNjQoMzgsIHJlcGVhdGVkRml4ZWQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFNmaXhlZDMyXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVNGaXhlZDMyKDM5LCByZXBlYXRlZFNmaXhlZDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRTZml4ZWQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVTRml4ZWQ2NCg0MCwgcmVwZWF0ZWRTZml4ZWQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEZsb2F0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUZsb2F0KDQxLCByZXBlYXRlZEZsb2F0Xy5nZXRGbG9hdChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZERvdWJsZV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVEb3VibGUoNDIsIHJlcGVhdGVkRG91YmxlXy5nZXREb3VibGUoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRCb29sXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUJvb2woNDMsIHJlcGVhdGVkQm9vbF8uZ2V0Qm9vbGVhbihpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFN0cmluZ18uc2l6ZSgpOyBpKyspIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDQ0LCByZXBlYXRlZFN0cmluZ18uZ2V0UmF3KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkQnl0ZXNfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlQnl0ZXMoNDUsIHJlcGVhdGVkQnl0ZXNfLmdldChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEdyb3VwXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUdyb3VwKDQ2LCByZXBlYXRlZEdyb3VwXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoNDgsIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uZ2V0KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSg0OSwgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uZ2V0KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDUwLCByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLmdldChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZE5lc3RlZEVudW1fLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSg1MSwgcmVwZWF0ZWROZXN0ZWRFbnVtXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRGb3JlaWduRW51bV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtKDUyLCByZXBlYXRlZEZvcmVpZ25FbnVtXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbXBvcnRFbnVtXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oNTMsIHJlcGVhdGVkSW1wb3J0RW51bV8uZ2V0KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkU3RyaW5nUGllY2VfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMud3JpdGVTdHJpbmcob3V0cHV0LCA1NCwgcmVwZWF0ZWRTdHJpbmdQaWVjZV8uZ2V0UmF3KGkpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkQ29yZF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDU1LCByZXBlYXRlZENvcmRfLmdldFJhdyhpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZExhenlNZXNzYWdlXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoNTcsIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmdldChpKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDgwMDAwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoNjEsIGRlZmF1bHRJbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDEwMDAwMDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDY0KDYyLCBkZWZhdWx0SW50NjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgyMDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzIoNjMsIGRlZmF1bHRVaW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHg0MDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50NjQoNjQsIGRlZmF1bHRVaW50NjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHg4MDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVTSW50MzIoNjUsIGRlZmF1bHRTaW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVTSW50NjQoNjYsIGRlZmF1bHRTaW50NjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVGaXhlZDMyKDY3LCBkZWZhdWx0Rml4ZWQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUZpeGVkNjQoNjgsIGRlZmF1bHRGaXhlZDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwMDgpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlU0ZpeGVkMzIoNjksIGRlZmF1bHRTZml4ZWQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZVNGaXhlZDY0KDcwLCBkZWZhdWx0U2ZpeGVkNjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVGbG9hdCg3MSwgZGVmYXVsdEZsb2F0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwNDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRG91YmxlKDcyLCBkZWZhdWx0RG91YmxlXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlQm9vbCg3MywgZGVmYXVsdEJvb2xfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDc0LCBkZWZhdWx0U3RyaW5nXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAyMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlQnl0ZXMoNzUsIGRlZmF1bHRCeXRlc18pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwNDAwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oODEsIGRlZmF1bHROZXN0ZWRFbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSg4MiwgZGVmYXVsdEZvcmVpZ25FbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDEwMDApICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSg4MywgZGVmYXVsdEltcG9ydEVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDg0LCBkZWZhdWx0U3RyaW5nUGllY2VfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwNDAwMCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDg1LCBkZWZhdWx0Q29yZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTExKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyKAogICAgICAgICAgICAxMTEsIChpbnQpKChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF8pKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMikgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMTEyLCAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTMpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDExMywgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE0KSB7CiAgICAgICAgb3V0cHV0LndyaXRlQnl0ZXMoCiAgICAgICAgICAgIDExNCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxMTUsIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwODAwMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigxMTYsIGRlY2VwdGl2ZWx5TmFtZWRMaXN0Xyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTcpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDExNywgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBvcHRpb25hbEludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDY0U2l6ZSgyLCBvcHRpb25hbEludDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZVVJbnQzMlNpemUoMywgb3B0aW9uYWxVaW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlVUludDY0U2l6ZSg0LCBvcHRpb25hbFVpbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVTSW50MzJTaXplKDUsIG9wdGlvbmFsU2ludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZVNJbnQ2NFNpemUoNiwgb3B0aW9uYWxTaW50NjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRml4ZWQzMlNpemUoNywgb3B0aW9uYWxGaXhlZDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUZpeGVkNjRTaXplKDgsIG9wdGlvbmFsRml4ZWQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMTAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVTRml4ZWQzMlNpemUoOSwgb3B0aW9uYWxTZml4ZWQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMjAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVTRml4ZWQ2NFNpemUoMTAsIG9wdGlvbmFsU2ZpeGVkNjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDQwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRmxvYXRTaXplKDExLCBvcHRpb25hbEZsb2F0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZURvdWJsZVNpemUoMTIsIG9wdGlvbmFsRG91YmxlXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDEwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUJvb2xTaXplKDEzLCBvcHRpb25hbEJvb2xfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmNvbXB1dGVTdHJpbmdTaXplKDE0LCBvcHRpb25hbFN0cmluZ18pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDA0MDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemUoMTUsIG9wdGlvbmFsQnl0ZXNfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwODAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlR3JvdXBTaXplKDE2LCBnZXRPcHRpb25hbEdyb3VwKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDEwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxOCwgZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDIwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxOSwgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDA0MDAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMjAsIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZSgpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDA4MDAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRW51bVNpemUoMjEsIG9wdGlvbmFsTmVzdGVkRW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMTAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZSgyMiwgb3B0aW9uYWxGb3JlaWduRW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMjAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZSgyMywgb3B0aW9uYWxJbXBvcnRFbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDA0MDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5jb21wdXRlU3RyaW5nU2l6ZSgyNCwgb3B0aW9uYWxTdHJpbmdQaWVjZV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwODAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoMjUsIG9wdGlvbmFsQ29yZF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAxMDAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyNiwgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAyMDAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyNywgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZSgpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwNDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMjgsIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhyZXBlYXRlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkSW50MzJMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQ2NFNpemVOb1RhZyhyZXBlYXRlZEludDY0Xy5nZXRMb25nKGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZEludDY0TGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkVWludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZVVJbnQzMlNpemVOb1RhZyhyZXBlYXRlZFVpbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZFVpbnQzMkxpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFVpbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVVSW50NjRTaXplTm9UYWcocmVwZWF0ZWRVaW50NjRfLmdldExvbmcoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkVWludDY0TGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkU2ludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZVNJbnQzMlNpemVOb1RhZyhyZXBlYXRlZFNpbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZFNpbnQzMkxpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFNpbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVTSW50NjRTaXplTm9UYWcocmVwZWF0ZWRTaW50NjRfLmdldExvbmcoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkU2ludDY0TGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDQgKiBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDggKiBnZXRSZXBlYXRlZEZpeGVkNjRMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRGaXhlZDY0TGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDQgKiBnZXRSZXBlYXRlZFNmaXhlZDMyTGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkU2ZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gOCAqIGdldFJlcGVhdGVkU2ZpeGVkNjRMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRTZml4ZWQ2NExpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZGF0YVNpemUgPSA0ICogZ2V0UmVwZWF0ZWRGbG9hdExpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZEZsb2F0TGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDggKiBnZXRSZXBlYXRlZERvdWJsZUxpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiBnZXRSZXBlYXRlZERvdWJsZUxpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZGF0YVNpemUgPSAxICogZ2V0UmVwZWF0ZWRCb29sTGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkQm9vbExpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFN0cmluZ18uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbXB1dGVTdHJpbmdTaXplTm9UYWcocmVwZWF0ZWRTdHJpbmdfLmdldFJhdyhpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRTdHJpbmdMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRCeXRlc18uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemVOb1RhZyhyZXBlYXRlZEJ5dGVzXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkQnl0ZXNMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRHcm91cF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlR3JvdXBTaXplKDQ2LCByZXBlYXRlZEdyb3VwXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5zaXplKCk7IGkrKykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg0OCwgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNDksIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmdldChpKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDUwLCByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLmdldChpKSk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZE5lc3RlZEVudW1fLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlRW51bVNpemVOb1RhZyhyZXBlYXRlZE5lc3RlZEVudW1fLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogcmVwZWF0ZWROZXN0ZWRFbnVtXy5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEZvcmVpZ25FbnVtXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUVudW1TaXplTm9UYWcocmVwZWF0ZWRGb3JlaWduRW51bV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDIgKiByZXBlYXRlZEZvcmVpZ25FbnVtXy5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEltcG9ydEVudW1fLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlRW51bVNpemVOb1RhZyhyZXBlYXRlZEltcG9ydEVudW1fLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogcmVwZWF0ZWRJbXBvcnRFbnVtXy5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZFN0cmluZ1BpZWNlXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tcHV0ZVN0cmluZ1NpemVOb1RhZyhyZXBlYXRlZFN0cmluZ1BpZWNlXy5nZXRSYXcoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIHNpemUgKz0gMiAqIGdldFJlcGVhdGVkU3RyaW5nUGllY2VMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRDb3JkXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tcHV0ZVN0cmluZ1NpemVOb1RhZyhyZXBlYXRlZENvcmRfLmdldFJhdyhpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSAyICogZ2V0UmVwZWF0ZWRDb3JkTGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkTGF6eU1lc3NhZ2VfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDU3LCByZXBlYXRlZExhenlNZXNzYWdlXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDA4MDAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoNjEsIGRlZmF1bHRJbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDEwMDAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQ2NFNpemUoNjIsIGRlZmF1bHRJbnQ2NF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDIwMDAwMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVVSW50MzJTaXplKDYzLCBkZWZhdWx0VWludDMyXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4NDAwMDAwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZVVJbnQ2NFNpemUoNjQsIGRlZmF1bHRVaW50NjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHg4MDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlU0ludDMyU2l6ZSg2NSwgZGVmYXVsdFNpbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVTSW50NjRTaXplKDY2LCBkZWZhdWx0U2ludDY0Xyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUZpeGVkMzJTaXplKDY3LCBkZWZhdWx0Rml4ZWQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVGaXhlZDY0U2l6ZSg2OCwgZGVmYXVsdEZpeGVkNjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlU0ZpeGVkMzJTaXplKDY5LCBkZWZhdWx0U2ZpeGVkMzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlU0ZpeGVkNjRTaXplKDcwLCBkZWZhdWx0U2ZpeGVkNjRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRmxvYXRTaXplKDcxLCBkZWZhdWx0RmxvYXRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRG91YmxlU2l6ZSg3MiwgZGVmYXVsdERvdWJsZV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwMDgwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCb29sU2l6ZSg3MywgZGVmYXVsdEJvb2xfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmNvbXB1dGVTdHJpbmdTaXplKDc0LCBkZWZhdWx0U3RyaW5nXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDAyMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUJ5dGVzU2l6ZSg3NSwgZGVmYXVsdEJ5dGVzXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDA0MDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUVudW1TaXplKDgxLCBkZWZhdWx0TmVzdGVkRW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAwODAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZSg4MiwgZGVmYXVsdEZvcmVpZ25FbnVtXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDEwMDApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUVudW1TaXplKDgzLCBkZWZhdWx0SW1wb3J0RW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAyMDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoODQsIGRlZmF1bHRTdHJpbmdQaWVjZV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDA0MDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoODUsIGRlZmF1bHRDb3JkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTEpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlVUludDMyU2l6ZSgKICAgICAgICAgICAgICAxMTEsIChpbnQpKChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF8pKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMikgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMTIsIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoMTEzLCBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTQpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlQnl0ZXNTaXplKAogICAgICAgICAgICAgIDExNCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDExNSwgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDA4MDAwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMTE2LCBkZWNlcHRpdmVseU5hbWVkTGlzdF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDExNywgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9iajsKCiAgICAgIGlmIChoYXNPcHRpb25hbEludDMyKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxJbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEludDMyKCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxJbnQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldE9wdGlvbmFsSW50MzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEludDY0KCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxJbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEludDY0KCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxJbnQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldE9wdGlvbmFsSW50NjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFVpbnQzMigpICE9IG90aGVyLmhhc09wdGlvbmFsVWludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsVWludDMyKCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxVaW50MzIoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRPcHRpb25hbFVpbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsVWludDY0KCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxVaW50NjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxVaW50NjQoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbFVpbnQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldE9wdGlvbmFsVWludDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxTaW50MzIoKSAhPSBvdGhlci5oYXNPcHRpb25hbFNpbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbFNpbnQzMigpKSB7CiAgICAgICAgaWYgKGdldE9wdGlvbmFsU2ludDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T3B0aW9uYWxTaW50MzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFNpbnQ2NCgpICE9IG90aGVyLmhhc09wdGlvbmFsU2ludDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsU2ludDY0KCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxTaW50NjQoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRPcHRpb25hbFNpbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsRml4ZWQzMigpICE9IG90aGVyLmhhc09wdGlvbmFsRml4ZWQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEZpeGVkMzIoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbEZpeGVkMzIoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRPcHRpb25hbEZpeGVkMzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEZpeGVkNjQoKSAhPSBvdGhlci5oYXNPcHRpb25hbEZpeGVkNjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxGaXhlZDY0KCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxGaXhlZDY0KCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T3B0aW9uYWxGaXhlZDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxTZml4ZWQzMigpICE9IG90aGVyLmhhc09wdGlvbmFsU2ZpeGVkMzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxTZml4ZWQzMigpKSB7CiAgICAgICAgaWYgKGdldE9wdGlvbmFsU2ZpeGVkMzIoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRPcHRpb25hbFNmaXhlZDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxTZml4ZWQ2NCgpICE9IG90aGVyLmhhc09wdGlvbmFsU2ZpeGVkNjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxTZml4ZWQ2NCgpKSB7CiAgICAgICAgaWYgKGdldE9wdGlvbmFsU2ZpeGVkNjQoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRPcHRpb25hbFNmaXhlZDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxGbG9hdCgpICE9IG90aGVyLmhhc09wdGlvbmFsRmxvYXQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxGbG9hdCgpKSB7CiAgICAgICAgaWYgKGphdmEubGFuZy5GbG9hdC5mbG9hdFRvSW50Qml0cyhnZXRPcHRpb25hbEZsb2F0KCkpCiAgICAgICAgICAgICE9IGphdmEubGFuZy5GbG9hdC5mbG9hdFRvSW50Qml0cygKICAgICAgICAgICAgICAgIG90aGVyLmdldE9wdGlvbmFsRmxvYXQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxEb3VibGUoKSAhPSBvdGhlci5oYXNPcHRpb25hbERvdWJsZSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbERvdWJsZSgpKSB7CiAgICAgICAgaWYgKGphdmEubGFuZy5Eb3VibGUuZG91YmxlVG9Mb25nQml0cyhnZXRPcHRpb25hbERvdWJsZSgpKQogICAgICAgICAgICAhPSBqYXZhLmxhbmcuRG91YmxlLmRvdWJsZVRvTG9uZ0JpdHMoCiAgICAgICAgICAgICAgICBvdGhlci5nZXRPcHRpb25hbERvdWJsZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEJvb2woKSAhPSBvdGhlci5oYXNPcHRpb25hbEJvb2woKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxCb29sKCkpIHsKICAgICAgICBpZiAoZ2V0T3B0aW9uYWxCb29sKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T3B0aW9uYWxCb29sKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxTdHJpbmcoKSAhPSBvdGhlci5oYXNPcHRpb25hbFN0cmluZygpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbFN0cmluZygpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbFN0cmluZygpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxTdHJpbmcoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxCeXRlcygpICE9IG90aGVyLmhhc09wdGlvbmFsQnl0ZXMoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxCeXRlcygpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbEJ5dGVzKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbEJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSAhPSBvdGhlci5oYXNPcHRpb25hbEdyb3VwKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxHcm91cCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxHcm91cCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSAhPSBvdGhlci5oYXNPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSAhPSBvdGhlci5oYXNPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSAhPSBvdGhlci5oYXNPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsTmVzdGVkRW51bSgpICE9IG90aGVyLmhhc09wdGlvbmFsTmVzdGVkRW51bSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbE5lc3RlZEVudW0oKSkgewogICAgICAgIGlmIChvcHRpb25hbE5lc3RlZEVudW1fICE9IG90aGVyLm9wdGlvbmFsTmVzdGVkRW51bV8pIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxGb3JlaWduRW51bSgpICE9IG90aGVyLmhhc09wdGlvbmFsRm9yZWlnbkVudW0oKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxGb3JlaWduRW51bSgpKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsRm9yZWlnbkVudW1fICE9IG90aGVyLm9wdGlvbmFsRm9yZWlnbkVudW1fKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsSW1wb3J0RW51bSgpICE9IG90aGVyLmhhc09wdGlvbmFsSW1wb3J0RW51bSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEltcG9ydEVudW0oKSkgewogICAgICAgIGlmIChvcHRpb25hbEltcG9ydEVudW1fICE9IG90aGVyLm9wdGlvbmFsSW1wb3J0RW51bV8pIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxTdHJpbmdQaWVjZSgpICE9IG90aGVyLmhhc09wdGlvbmFsU3RyaW5nUGllY2UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxTdHJpbmdQaWVjZSgpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbFN0cmluZ1BpZWNlKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbFN0cmluZ1BpZWNlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQ29yZCgpICE9IG90aGVyLmhhc09wdGlvbmFsQ29yZCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbENvcmQoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxDb3JkKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbENvcmQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbExhenlNZXNzYWdlKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxMYXp5TWVzc2FnZSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbExhenlNZXNzYWdlKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsTGF6eU1lc3NhZ2UoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsTGF6eU1lc3NhZ2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSAhPSBvdGhlci5oYXNPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFJlcGVhdGVkSW50MzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZEludDY0TGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkSW50NjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRVaW50MzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRVaW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRVaW50NjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRVaW50NjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRTaW50MzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRTaW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRTaW50NjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRTaW50NjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZEZpeGVkNjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRGaXhlZDY0TGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkU2ZpeGVkMzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRTZml4ZWQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZFNmaXhlZDY0TGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkU2ZpeGVkNjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRGbG9hdExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEZsb2F0TGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkRG91YmxlTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkRG91YmxlTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkQm9vbExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEJvb2xMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRTdHJpbmdMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRTdHJpbmdMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRCeXRlc0xpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEJ5dGVzTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkR3JvdXBMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRHcm91cExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIXJlcGVhdGVkTmVzdGVkRW51bV8uZXF1YWxzKG90aGVyLnJlcGVhdGVkTmVzdGVkRW51bV8pKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghcmVwZWF0ZWRGb3JlaWduRW51bV8uZXF1YWxzKG90aGVyLnJlcGVhdGVkRm9yZWlnbkVudW1fKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIXJlcGVhdGVkSW1wb3J0RW51bV8uZXF1YWxzKG90aGVyLnJlcGVhdGVkSW1wb3J0RW51bV8pKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZFN0cmluZ1BpZWNlTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFJlcGVhdGVkQ29yZExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZENvcmRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZExhenlNZXNzYWdlTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdEludDMyKCkgIT0gb3RoZXIuaGFzRGVmYXVsdEludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRJbnQzMigpKSB7CiAgICAgICAgaWYgKGdldERlZmF1bHRJbnQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRJbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRJbnQ2NCgpICE9IG90aGVyLmhhc0RlZmF1bHRJbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0SW50NjQoKSkgewogICAgICAgIGlmIChnZXREZWZhdWx0SW50NjQoKQogICAgICAgICAgICAhPSBvdGhlci5nZXREZWZhdWx0SW50NjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0VWludDMyKCkgIT0gb3RoZXIuaGFzRGVmYXVsdFVpbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0VWludDMyKCkpIHsKICAgICAgICBpZiAoZ2V0RGVmYXVsdFVpbnQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRVaW50MzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0VWludDY0KCkgIT0gb3RoZXIuaGFzRGVmYXVsdFVpbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0VWludDY0KCkpIHsKICAgICAgICBpZiAoZ2V0RGVmYXVsdFVpbnQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRVaW50NjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U2ludDMyKCkgIT0gb3RoZXIuaGFzRGVmYXVsdFNpbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0U2ludDMyKCkpIHsKICAgICAgICBpZiAoZ2V0RGVmYXVsdFNpbnQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRTaW50MzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U2ludDY0KCkgIT0gb3RoZXIuaGFzRGVmYXVsdFNpbnQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0U2ludDY0KCkpIHsKICAgICAgICBpZiAoZ2V0RGVmYXVsdFNpbnQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRTaW50NjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Rml4ZWQzMigpICE9IG90aGVyLmhhc0RlZmF1bHRGaXhlZDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRGaXhlZDMyKCkpIHsKICAgICAgICBpZiAoZ2V0RGVmYXVsdEZpeGVkMzIoKQogICAgICAgICAgICAhPSBvdGhlci5nZXREZWZhdWx0Rml4ZWQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRGaXhlZDY0KCkgIT0gb3RoZXIuaGFzRGVmYXVsdEZpeGVkNjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdEZpeGVkNjQoKSkgewogICAgICAgIGlmIChnZXREZWZhdWx0Rml4ZWQ2NCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRGaXhlZDY0KCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdFNmaXhlZDMyKCkgIT0gb3RoZXIuaGFzRGVmYXVsdFNmaXhlZDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRTZml4ZWQzMigpKSB7CiAgICAgICAgaWYgKGdldERlZmF1bHRTZml4ZWQzMigpCiAgICAgICAgICAgICE9IG90aGVyLmdldERlZmF1bHRTZml4ZWQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTZml4ZWQ2NCgpICE9IG90aGVyLmhhc0RlZmF1bHRTZml4ZWQ2NCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0U2ZpeGVkNjQoKSkgewogICAgICAgIGlmIChnZXREZWZhdWx0U2ZpeGVkNjQoKQogICAgICAgICAgICAhPSBvdGhlci5nZXREZWZhdWx0U2ZpeGVkNjQoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0RmxvYXQoKSAhPSBvdGhlci5oYXNEZWZhdWx0RmxvYXQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdEZsb2F0KCkpIHsKICAgICAgICBpZiAoamF2YS5sYW5nLkZsb2F0LmZsb2F0VG9JbnRCaXRzKGdldERlZmF1bHRGbG9hdCgpKQogICAgICAgICAgICAhPSBqYXZhLmxhbmcuRmxvYXQuZmxvYXRUb0ludEJpdHMoCiAgICAgICAgICAgICAgICBvdGhlci5nZXREZWZhdWx0RmxvYXQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdERvdWJsZSgpICE9IG90aGVyLmhhc0RlZmF1bHREb3VibGUoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdERvdWJsZSgpKSB7CiAgICAgICAgaWYgKGphdmEubGFuZy5Eb3VibGUuZG91YmxlVG9Mb25nQml0cyhnZXREZWZhdWx0RG91YmxlKCkpCiAgICAgICAgICAgICE9IGphdmEubGFuZy5Eb3VibGUuZG91YmxlVG9Mb25nQml0cygKICAgICAgICAgICAgICAgIG90aGVyLmdldERlZmF1bHREb3VibGUoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEJvb2woKSAhPSBvdGhlci5oYXNEZWZhdWx0Qm9vbCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0Qm9vbCgpKSB7CiAgICAgICAgaWYgKGdldERlZmF1bHRCb29sKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVmYXVsdEJvb2woKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U3RyaW5nKCkgIT0gb3RoZXIuaGFzRGVmYXVsdFN0cmluZygpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0U3RyaW5nKCkpIHsKICAgICAgICBpZiAoIWdldERlZmF1bHRTdHJpbmcoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldERlZmF1bHRTdHJpbmcoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEJ5dGVzKCkgIT0gb3RoZXIuaGFzRGVmYXVsdEJ5dGVzKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHRCeXRlcygpKSB7CiAgICAgICAgaWYgKCFnZXREZWZhdWx0Qnl0ZXMoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldERlZmF1bHRCeXRlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0TmVzdGVkRW51bSgpICE9IG90aGVyLmhhc0RlZmF1bHROZXN0ZWRFbnVtKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlZmF1bHROZXN0ZWRFbnVtKCkpIHsKICAgICAgICBpZiAoZGVmYXVsdE5lc3RlZEVudW1fICE9IG90aGVyLmRlZmF1bHROZXN0ZWRFbnVtXykgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Rm9yZWlnbkVudW0oKSAhPSBvdGhlci5oYXNEZWZhdWx0Rm9yZWlnbkVudW0oKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdEZvcmVpZ25FbnVtKCkpIHsKICAgICAgICBpZiAoZGVmYXVsdEZvcmVpZ25FbnVtXyAhPSBvdGhlci5kZWZhdWx0Rm9yZWlnbkVudW1fKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRJbXBvcnRFbnVtKCkgIT0gb3RoZXIuaGFzRGVmYXVsdEltcG9ydEVudW0oKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVmYXVsdEltcG9ydEVudW0oKSkgewogICAgICAgIGlmIChkZWZhdWx0SW1wb3J0RW51bV8gIT0gb3RoZXIuZGVmYXVsdEltcG9ydEVudW1fKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTdHJpbmdQaWVjZSgpICE9IG90aGVyLmhhc0RlZmF1bHRTdHJpbmdQaWVjZSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0U3RyaW5nUGllY2UoKSkgewogICAgICAgIGlmICghZ2V0RGVmYXVsdFN0cmluZ1BpZWNlKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXREZWZhdWx0U3RyaW5nUGllY2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdENvcmQoKSAhPSBvdGhlci5oYXNEZWZhdWx0Q29yZCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWZhdWx0Q29yZCgpKSB7CiAgICAgICAgaWYgKCFnZXREZWZhdWx0Q29yZCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RGVmYXVsdENvcmQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVjZXB0aXZlbHlOYW1lZExpc3QoKSAhPSBvdGhlci5oYXNEZWNlcHRpdmVseU5hbWVkTGlzdCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNEZWNlcHRpdmVseU5hbWVkTGlzdCgpKSB7CiAgICAgICAgaWYgKGdldERlY2VwdGl2ZWx5TmFtZWRMaXN0KCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVjZXB0aXZlbHlOYW1lZExpc3QoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0T25lb2ZGaWVsZENhc2UoKS5lcXVhbHMob3RoZXIuZ2V0T25lb2ZGaWVsZENhc2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgc3dpdGNoIChvbmVvZkZpZWxkQ2FzZV8pIHsKICAgICAgICBjYXNlIDExMToKICAgICAgICAgIGlmIChnZXRPbmVvZlVpbnQzMigpCiAgICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T25lb2ZVaW50MzIoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMTI6CiAgICAgICAgICBpZiAoIWdldE9uZW9mTmVzdGVkTWVzc2FnZSgpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZk5lc3RlZE1lc3NhZ2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTEzOgogICAgICAgICAgaWYgKCFnZXRPbmVvZlN0cmluZygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZlN0cmluZygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMTQ6CiAgICAgICAgICBpZiAoIWdldE9uZW9mQnl0ZXMoKQogICAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T25lb2ZCeXRlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMTU6CiAgICAgICAgICBpZiAoIWdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoKQogICAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMTc6CiAgICAgICAgICBpZiAoIWdldE9uZW9mTmVzdGVkTWVzc2FnZTIoKQogICAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlMigpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAwOgogICAgICAgIGRlZmF1bHQ6CiAgICAgIH0KICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoaGFzT3B0aW9uYWxJbnQzMigpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsSW50MzIoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxJbnQ2NCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGdldE9wdGlvbmFsSW50NjQoKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsVWludDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9VSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsVWludDMyKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsVWludDY0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9VSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGdldE9wdGlvbmFsVWludDY0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFNpbnQzMigpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfU0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbFNpbnQzMigpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFNpbnQ2NCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfU0lOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmhhc2hMb25nKAogICAgICAgICAgICBnZXRPcHRpb25hbFNpbnQ2NCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxGaXhlZDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9GSVhFRDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbEZpeGVkMzIoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxGaXhlZDY0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9GSVhFRDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmhhc2hMb25nKAogICAgICAgICAgICBnZXRPcHRpb25hbEZpeGVkNjQoKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU2ZpeGVkMzIoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX1NGSVhFRDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbFNmaXhlZDMyKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU2ZpeGVkNjQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX1NGSVhFRDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmhhc2hMb25nKAogICAgICAgICAgICBnZXRPcHRpb25hbFNmaXhlZDY0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEZsb2F0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9GTE9BVF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgamF2YS5sYW5nLkZsb2F0LmZsb2F0VG9JbnRCaXRzKAogICAgICAgICAgICBnZXRPcHRpb25hbEZsb2F0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbERvdWJsZSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfRE9VQkxFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmhhc2hMb25nKAogICAgICAgICAgICBqYXZhLmxhbmcuRG91YmxlLmRvdWJsZVRvTG9uZ0JpdHMoZ2V0T3B0aW9uYWxEb3VibGUoKSkpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEJvb2woKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0JPT0xfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaEJvb2xlYW4oCiAgICAgICAgICAgIGdldE9wdGlvbmFsQm9vbCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxTdHJpbmcoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX1NUUklOR19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxTdHJpbmcoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEJ5dGVzKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9CWVRFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxCeXRlcygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMR1JPVVBfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsR3JvdXAoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX05FU1RFRF9NRVNTQUdFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9GT1JFSUdOX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0lNUE9SVF9NRVNTQUdFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbEltcG9ydE1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbE5lc3RlZEVudW0oKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX05FU1RFRF9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBvcHRpb25hbE5lc3RlZEVudW1fOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEZvcmVpZ25FbnVtKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9GT1JFSUdOX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIG9wdGlvbmFsRm9yZWlnbkVudW1fOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEltcG9ydEVudW0oKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0lNUE9SVF9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBvcHRpb25hbEltcG9ydEVudW1fOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFN0cmluZ1BpZWNlKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsU3RyaW5nUGllY2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbENvcmQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0NPUkRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsQ29yZCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfUFVCTElDX0lNUE9SVF9NRVNTQUdFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbExhenlNZXNzYWdlKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9MQVpZX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfVU5WRVJJRklFRF9MQVpZX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkSW50MzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRJbnQ2NENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkSW50NjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRVaW50MzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX1VJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRVaW50MzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRVaW50NjRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX1VJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRVaW50NjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRTaW50MzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX1NJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRTaW50MzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRTaW50NjRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX1NJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRTaW50NjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9GSVhFRDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRGaXhlZDY0Q291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9GSVhFRDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZEZpeGVkNjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRTZml4ZWQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfU0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkU2ZpeGVkMzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRTZml4ZWQ2NENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfU0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkU2ZpeGVkNjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRGbG9hdENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfRkxPQVRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkRmxvYXRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWREb3VibGVDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0RPVUJMRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWREb3VibGVMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRCb29sQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9CT09MX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZEJvb2xMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRTdHJpbmdDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX1NUUklOR19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRTdHJpbmdMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRCeXRlc0NvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfQllURVNfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkQnl0ZXNMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRHcm91cENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURHUk9VUF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRHcm91cExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX05FU1RFRF9NRVNTQUdFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfRk9SRUlHTl9NRVNTQUdFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfSU1QT1JUX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZE5lc3RlZEVudW1Db3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX05FU1RFRF9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyByZXBlYXRlZE5lc3RlZEVudW1fLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGdldFJlcGVhdGVkRm9yZWlnbkVudW1Db3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0ZPUkVJR05fRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgcmVwZWF0ZWRGb3JlaWduRW51bV8uaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9JTVBPUlRfRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgcmVwZWF0ZWRJbXBvcnRFbnVtXy5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZFN0cmluZ1BpZWNlQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkU3RyaW5nUGllY2VMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRDb3JkQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9DT1JEX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZENvcmRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfTEFaWV9NRVNTQUdFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZExhenlNZXNzYWdlTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRJbnQzMigpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RGVmYXVsdEludDMyKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRJbnQ2NCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9JTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgZ2V0RGVmYXVsdEludDY0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0VWludDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX1VJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RGVmYXVsdFVpbnQzMigpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0VWludDY0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX1VJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoTG9uZygKICAgICAgICAgICAgZ2V0RGVmYXVsdFVpbnQ2NCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdFNpbnQzMigpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9TSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlZmF1bHRTaW50MzIoKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdFNpbnQ2NCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9TSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGdldERlZmF1bHRTaW50NjQoKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRGaXhlZDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlZmF1bHRGaXhlZDMyKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRGaXhlZDY0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGdldERlZmF1bHRGaXhlZDY0KCkpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U2ZpeGVkMzIoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfU0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlZmF1bHRTZml4ZWQzMigpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U2ZpeGVkNjQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfU0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGdldERlZmF1bHRTZml4ZWQ2NCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEZsb2F0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0ZMT0FUX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBqYXZhLmxhbmcuRmxvYXQuZmxvYXRUb0ludEJpdHMoCiAgICAgICAgICAgIGdldERlZmF1bHRGbG9hdCgpKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdERvdWJsZSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9ET1VCTEVfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuaGFzaExvbmcoCiAgICAgICAgICAgIGphdmEubGFuZy5Eb3VibGUuZG91YmxlVG9Mb25nQml0cyhnZXREZWZhdWx0RG91YmxlKCkpKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEJvb2woKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfQk9PTF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5oYXNoQm9vbGVhbigKICAgICAgICAgICAgZ2V0RGVmYXVsdEJvb2woKSk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlZmF1bHRTdHJpbmcoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfU1RSSU5HX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZWZhdWx0U3RyaW5nKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVmYXVsdEJ5dGVzKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUZBVUxUX0JZVEVTX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZWZhdWx0Qnl0ZXMoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0TmVzdGVkRW51bSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9ORVNURURfRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZGVmYXVsdE5lc3RlZEVudW1fOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Rm9yZWlnbkVudW0oKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfRk9SRUlHTl9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBkZWZhdWx0Rm9yZWlnbkVudW1fOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0SW1wb3J0RW51bSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9JTVBPUlRfRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZGVmYXVsdEltcG9ydEVudW1fOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0U3RyaW5nUGllY2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFRkFVTFRfU1RSSU5HX1BJRUNFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZWZhdWx0U3RyaW5nUGllY2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNEZWZhdWx0Q29yZCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVGQVVMVF9DT1JEX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZWZhdWx0Q29yZCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlY2VwdGl2ZWx5TmFtZWRMaXN0KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBERUNFUFRJVkVMWV9OQU1FRF9MSVNUX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZWNlcHRpdmVseU5hbWVkTGlzdCgpOwogICAgICB9CiAgICAgIHN3aXRjaCAob25lb2ZGaWVsZENhc2VfKSB7CiAgICAgICAgY2FzZSAxMTE6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9VSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZVaW50MzIoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTEyOgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfTkVTVEVEX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTEzOgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfU1RSSU5HX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9uZW9mU3RyaW5nKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTE0OgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfQllURVNfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZCeXRlcygpLmhhc2hDb2RlKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDExNToKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX0xBWllfTkVTVEVEX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDExNzoKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX05FU1RFRF9NRVNTQUdFMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZk5lc3RlZE1lc3NhZ2UyKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMDoKICAgICAgICBkZWZhdWx0OgogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFNhbWUgYXMgVGVzdEFsbFR5cGVzIGJ1dCB3aXRoIHRoZSBsaXRlIHJ1bnRpbWUuCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCkgewogICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMpIHsKICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZUZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRSZXBlYXRlZEdyb3VwRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgYml0RmllbGQxXyA9IDA7CiAgICAgICAgYml0RmllbGQyXyA9IDA7CiAgICAgICAgb3B0aW9uYWxJbnQzMl8gPSAwOwogICAgICAgIG9wdGlvbmFsSW50NjRfID0gMEw7CiAgICAgICAgb3B0aW9uYWxVaW50MzJfID0gMDsKICAgICAgICBvcHRpb25hbFVpbnQ2NF8gPSAwTDsKICAgICAgICBvcHRpb25hbFNpbnQzMl8gPSAwOwogICAgICAgIG9wdGlvbmFsU2ludDY0XyA9IDBMOwogICAgICAgIG9wdGlvbmFsRml4ZWQzMl8gPSAwOwogICAgICAgIG9wdGlvbmFsRml4ZWQ2NF8gPSAwTDsKICAgICAgICBvcHRpb25hbFNmaXhlZDMyXyA9IDA7CiAgICAgICAgb3B0aW9uYWxTZml4ZWQ2NF8gPSAwTDsKICAgICAgICBvcHRpb25hbEZsb2F0XyA9IDBGOwogICAgICAgIG9wdGlvbmFsRG91YmxlXyA9IDBEOwogICAgICAgIG9wdGlvbmFsQm9vbF8gPSBmYWxzZTsKICAgICAgICBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgICAgICBvcHRpb25hbEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgICBvcHRpb25hbEdyb3VwXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9wdGlvbmFsTmVzdGVkRW51bV8gPSAxOwogICAgICAgIG9wdGlvbmFsRm9yZWlnbkVudW1fID0gNDsKICAgICAgICBvcHRpb25hbEltcG9ydEVudW1fID0gNzsKICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9ICIiOwogICAgICAgIG9wdGlvbmFsQ29yZF8gPSAiIjsKICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXBlYXRlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHJlcGVhdGVkSW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIHJlcGVhdGVkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHJlcGVhdGVkVWludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICByZXBlYXRlZFNpbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICByZXBlYXRlZFNpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICByZXBlYXRlZFNmaXhlZDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICByZXBlYXRlZEZsb2F0XyA9IGVtcHR5RmxvYXRMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRCb29sXyA9IGVtcHR5Qm9vbGVhbkxpc3QoKTsKICAgICAgICByZXBlYXRlZFN0cmluZ18gPQogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRCeXRlc18gPSBlbXB0eUxpc3QoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNsYXNzKTsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IG51bGw7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDA0MDApOwogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAwODAwKTsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IG51bGw7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDEwMDApOwogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDA0MDAwKTsKICAgICAgICByZXBlYXRlZEZvcmVpZ25FbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwODAwMCk7CiAgICAgICAgcmVwZWF0ZWRJbXBvcnRFbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAxMDAwMCk7CiAgICAgICAgcmVwZWF0ZWRTdHJpbmdQaWVjZV8gPQogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgICAgcmVwZWF0ZWRDb3JkXyA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdC5lbXB0eUxpc3QoKTsKICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwODAwMDApOwogICAgICAgIGRlZmF1bHRJbnQzMl8gPSA0MTsKICAgICAgICBkZWZhdWx0SW50NjRfID0gNDJMOwogICAgICAgIGRlZmF1bHRVaW50MzJfID0gNDM7CiAgICAgICAgZGVmYXVsdFVpbnQ2NF8gPSA0NEw7CiAgICAgICAgZGVmYXVsdFNpbnQzMl8gPSAtNDU7CiAgICAgICAgZGVmYXVsdFNpbnQ2NF8gPSA0Nkw7CiAgICAgICAgZGVmYXVsdEZpeGVkMzJfID0gNDc7CiAgICAgICAgZGVmYXVsdEZpeGVkNjRfID0gNDhMOwogICAgICAgIGRlZmF1bHRTZml4ZWQzMl8gPSA0OTsKICAgICAgICBkZWZhdWx0U2ZpeGVkNjRfID0gLTUwTDsKICAgICAgICBkZWZhdWx0RmxvYXRfID0gNTEuNUY7CiAgICAgICAgZGVmYXVsdERvdWJsZV8gPSA1MjAwMEQ7CiAgICAgICAgZGVmYXVsdEJvb2xfID0gdHJ1ZTsKICAgICAgICBkZWZhdWx0U3RyaW5nXyA9ICJoZWxsbyI7CiAgICAgICAgZGVmYXVsdEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoIndvcmxkIik7CiAgICAgICAgZGVmYXVsdE5lc3RlZEVudW1fID0gMjsKICAgICAgICBkZWZhdWx0Rm9yZWlnbkVudW1fID0gNTsKICAgICAgICBkZWZhdWx0SW1wb3J0RW51bV8gPSA4OwogICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSAiYWJjIjsKICAgICAgICBkZWZhdWx0Q29yZF8gPSAiMTIzIjsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgZGVjZXB0aXZlbHlOYW1lZExpc3RfID0gMDsKICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKHRoaXMpOwogICAgICAgIGJ1aWxkUGFydGlhbFJlcGVhdGVkRmllbGRzKHJlc3VsdCk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBpZiAoYml0RmllbGQxXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDEocmVzdWx0KTsgfQogICAgICAgIGlmIChiaXRGaWVsZDJfICE9IDApIHsgYnVpbGRQYXJ0aWFsMihyZXN1bHQpOyB9CiAgICAgICAgYnVpbGRQYXJ0aWFsT25lb2ZzKHJlc3VsdCk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWxSZXBlYXRlZEZpZWxkcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlc3VsdCkgewogICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQxXyAmIDB4MDAwMDA0MDApICE9IDApKSB7CiAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRHcm91cF8pOwogICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDQwMCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRHcm91cF8gPSByZXBlYXRlZEdyb3VwXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkR3JvdXBfID0gcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMDgwMCkgIT0gMCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8pOwogICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDgwMCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyA9IHJlcGVhdGVkTmVzdGVkTWVzc2FnZV87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZE5lc3RlZE1lc3NhZ2VfID0gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyk7CiAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAxMDAwKTsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8gPSByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDAyMDAwKSAhPSAwKSkgewogICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyk7CiAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkSW1wb3J0TWVzc2FnZV8gPSByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDAwNDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkRW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZE5lc3RlZEVudW1fKTsKICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDA0MDAwKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnJlcGVhdGVkTmVzdGVkRW51bV8gPSByZXBlYXRlZE5lc3RlZEVudW1fOwogICAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDA4MDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZEZvcmVpZ25FbnVtXyk7CiAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwODAwMCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5yZXBlYXRlZEZvcmVpZ25FbnVtXyA9IHJlcGVhdGVkRm9yZWlnbkVudW1fOwogICAgICAgIGlmICgoKGJpdEZpZWxkMV8gJiAweDAwMDEwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRFbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkSW1wb3J0RW51bV8pOwogICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMTAwMDApOwogICAgICAgIH0KICAgICAgICByZXN1bHQucmVwZWF0ZWRJbXBvcnRFbnVtXyA9IHJlcGVhdGVkSW1wb3J0RW51bV87CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDFfICYgMHgwMDA4MDAwMCkgIT0gMCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZExhenlNZXNzYWdlXyk7CiAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDgwMDAwKTsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZExhenlNZXNzYWdlXyA9IHJlcGVhdGVkTGF6eU1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRMYXp5TWVzc2FnZV8gPSByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxJbnQzMl8gPSBvcHRpb25hbEludDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEludDY0XyA9IG9wdGlvbmFsSW50NjRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsVWludDMyXyA9IG9wdGlvbmFsVWludDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbFVpbnQ2NF8gPSBvcHRpb25hbFVpbnQ2NF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxTaW50MzJfID0gb3B0aW9uYWxTaW50MzJfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDIwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsU2ludDY0XyA9IG9wdGlvbmFsU2ludDY0XzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEZpeGVkMzJfID0gb3B0aW9uYWxGaXhlZDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA4MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEZpeGVkNjRfID0gb3B0aW9uYWxGaXhlZDY0XzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbFNmaXhlZDMyXyA9IG9wdGlvbmFsU2ZpeGVkMzJfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMjAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsU2ZpeGVkNjRfID0gb3B0aW9uYWxTZml4ZWQ2NF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDA0MDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxGbG9hdF8gPSBvcHRpb25hbEZsb2F0XzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDgwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbERvdWJsZV8gPSBvcHRpb25hbERvdWJsZV87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDEwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxCb29sXyA9IG9wdGlvbmFsQm9vbF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDIwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxTdHJpbmdfID0gb3B0aW9uYWxTdHJpbmdfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDA0MDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsQnl0ZXNfID0gb3B0aW9uYWxCeXRlc187CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDgwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxHcm91cF8gPSBvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gb3B0aW9uYWxHcm91cF8KICAgICAgICAgICAgICA6IG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDEwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsTmVzdGVkTWVzc2FnZV8gPSBvcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgPyBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfCiAgICAgICAgICAgICAgOiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDIwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfID0gb3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfCiAgICAgICAgICAgICAgOiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAyMDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDA0MDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEltcG9ydE1lc3NhZ2VfID0gb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gb3B0aW9uYWxJbXBvcnRNZXNzYWdlXwogICAgICAgICAgICAgIDogb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDA0MDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDA4MDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbE5lc3RlZEVudW1fID0gb3B0aW9uYWxOZXN0ZWRFbnVtXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDA4MDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDEwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEZvcmVpZ25FbnVtXyA9IG9wdGlvbmFsRm9yZWlnbkVudW1fOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMTAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMjAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsSW1wb3J0RW51bV8gPSBvcHRpb25hbEltcG9ydEVudW1fOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMjAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwNDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsU3RyaW5nUGllY2VfID0gb3B0aW9uYWxTdHJpbmdQaWVjZV87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDA0MDAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDA4MDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxDb3JkXyA9IG9wdGlvbmFsQ29yZF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDA4MDAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDEwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXyA9IG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8KICAgICAgICAgICAgICA6IG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDEwMDAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDIwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQub3B0aW9uYWxMYXp5TWVzc2FnZV8gPSBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gb3B0aW9uYWxMYXp5TWVzc2FnZV8KICAgICAgICAgICAgICA6IG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAyMDAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDA0MDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyA9IG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfCiAgICAgICAgICAgICAgOiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDQwMDAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDgwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRJbnQzMl8gPSByZXBlYXRlZEludDMyXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgxMDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEludDY0XyA9IHJlcGVhdGVkSW50NjRfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDIwMDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZFVpbnQzMl8gPSByZXBlYXRlZFVpbnQzMl87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4NDAwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZFVpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkVWludDY0XyA9IHJlcGVhdGVkVWludDY0XzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHg4MDAwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkU2ludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRTaW50MzJfID0gcmVwZWF0ZWRTaW50MzJfOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMV8gPSBiaXRGaWVsZDFfOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZFNpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkU2ludDY0XyA9IHJlcGVhdGVkU2ludDY0XzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkRml4ZWQzMl8gPSByZXBlYXRlZEZpeGVkMzJfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRGaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRGaXhlZDY0XyA9IHJlcGVhdGVkRml4ZWQ2NF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDAwMDAwMDgpICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZFNmaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRTZml4ZWQzMl8gPSByZXBlYXRlZFNmaXhlZDMyXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZFNmaXhlZDY0XyA9IHJlcGVhdGVkU2ZpeGVkNjRfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMDAwMDIwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRGbG9hdF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkRmxvYXRfID0gcmVwZWF0ZWRGbG9hdF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDAwMDAwNDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZERvdWJsZV8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkRG91YmxlXyA9IHJlcGVhdGVkRG91YmxlXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDAwMDA4MCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkQm9vbF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkQm9vbF8gPSByZXBlYXRlZEJvb2xfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMDAwMTAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRTdHJpbmdfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZFN0cmluZ18gPSByZXBlYXRlZFN0cmluZ187CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDAwMDAyMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEJ5dGVzXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRCeXRlc18gPSByZXBlYXRlZEJ5dGVzXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMDAyMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZFN0cmluZ1BpZWNlXyA9IHJlcGVhdGVkU3RyaW5nUGllY2VfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMDQwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRDb3JkXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRDb3JkXyA9IHJlcGVhdGVkQ29yZF87CiAgICAgICAgfQogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMTAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRJbnQzMl8gPSBkZWZhdWx0SW50MzJfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDA4MDAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwMjAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRJbnQ2NF8gPSBkZWZhdWx0SW50NjRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDEwMDAwMDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDAwNDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRVaW50MzJfID0gZGVmYXVsdFVpbnQzMl87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MjAwMDAwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MDA4MDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdFVpbnQ2NF8gPSBkZWZhdWx0VWludDY0XzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHg0MDAwMDAwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMTAwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0U2ludDMyXyA9IGRlZmF1bHRTaW50MzJfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDgwMDAwMDAwOwogICAgICAgIH0KICAgICAgICBpbnQgdG9fYml0RmllbGQxXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwMjAwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0U2ludDY0XyA9IGRlZmF1bHRTaW50NjRfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMV8gJiAweDA0MDAwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRGaXhlZDMyXyA9IGRlZmF1bHRGaXhlZDMyXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwMDAwMjsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDFfICYgMHgwODAwMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0Rml4ZWQ2NF8gPSBkZWZhdWx0Rml4ZWQ2NF87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MTAwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdFNmaXhlZDMyXyA9IGRlZmF1bHRTZml4ZWQzMl87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4MjAwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdFNmaXhlZDY0XyA9IGRlZmF1bHRTZml4ZWQ2NF87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4NDAwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdEZsb2F0XyA9IGRlZmF1bHRGbG9hdF87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQxXyAmIDB4ODAwMDAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdERvdWJsZV8gPSBkZWZhdWx0RG91YmxlXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwMDA0MDsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgICByZXN1bHQuYml0RmllbGQxXyB8PSB0b19iaXRGaWVsZDFfOwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMl8gPSBiaXRGaWVsZDJfOwogICAgICAgIGludCB0b19iaXRGaWVsZDFfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMl8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRCb29sXyA9IGRlZmF1bHRCb29sXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwMDA4MDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDJfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0U3RyaW5nXyA9IGRlZmF1bHRTdHJpbmdfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAwMTAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMl8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHRCeXRlc18gPSBkZWZhdWx0Qnl0ZXNfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDAwMjAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMl8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlZmF1bHROZXN0ZWRFbnVtXyA9IGRlZmF1bHROZXN0ZWRFbnVtXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwMDQwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDJfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0Rm9yZWlnbkVudW1fID0gZGVmYXVsdEZvcmVpZ25FbnVtXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwMDgwMDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDJfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZWZhdWx0SW1wb3J0RW51bV8gPSBkZWZhdWx0SW1wb3J0RW51bV87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQyXyAmIDB4MDAwMDAwNDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdFN0cmluZ1BpZWNlXyA9IGRlZmF1bHRTdHJpbmdQaWVjZV87CiAgICAgICAgICB0b19iaXRGaWVsZDFfIHw9IDB4MDAwMDIwMDA7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQyXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVmYXVsdENvcmRfID0gZGVmYXVsdENvcmRfOwogICAgICAgICAgdG9fYml0RmllbGQxXyB8PSAweDAwMDA0MDAwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMl8gJiAweDAwMDA0MDAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlY2VwdGl2ZWx5TmFtZWRMaXN0XyA9IGRlY2VwdGl2ZWx5TmFtZWRMaXN0XzsKICAgICAgICAgIHRvX2JpdEZpZWxkMV8gfD0gMHgwMDAwODAwMDsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMV8gfD0gdG9fYml0RmllbGQxXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbE9uZW9mcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlc3VsdCkgewogICAgICAgIHJlc3VsdC5vbmVvZkZpZWxkQ2FzZV8gPSBvbmVvZkZpZWxkQ2FzZV87CiAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRfID0gdGhpcy5vbmVvZkZpZWxkXzsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMiAmJgogICAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXN1bHQub25lb2ZGaWVsZF8gPSBvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNSAmJgogICAgICAgICAgICBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRfID0gb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3ICYmCiAgICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXN1bHQub25lb2ZGaWVsZF8gPSBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsSW50MzIoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxJbnQzMihvdGhlci5nZXRPcHRpb25hbEludDMyKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxJbnQ2NCgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEludDY0KG90aGVyLmdldE9wdGlvbmFsSW50NjQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbFVpbnQzMigpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbFVpbnQzMihvdGhlci5nZXRPcHRpb25hbFVpbnQzMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsVWludDY0KCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsVWludDY0KG90aGVyLmdldE9wdGlvbmFsVWludDY0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxTaW50MzIoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxTaW50MzIob3RoZXIuZ2V0T3B0aW9uYWxTaW50MzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbFNpbnQ2NCgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbFNpbnQ2NChvdGhlci5nZXRPcHRpb25hbFNpbnQ2NCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsRml4ZWQzMigpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEZpeGVkMzIob3RoZXIuZ2V0T3B0aW9uYWxGaXhlZDMyKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxGaXhlZDY0KCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsRml4ZWQ2NChvdGhlci5nZXRPcHRpb25hbEZpeGVkNjQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbFNmaXhlZDMyKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsU2ZpeGVkMzIob3RoZXIuZ2V0T3B0aW9uYWxTZml4ZWQzMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsU2ZpeGVkNjQoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxTZml4ZWQ2NChvdGhlci5nZXRPcHRpb25hbFNmaXhlZDY0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxGbG9hdCgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEZsb2F0KG90aGVyLmdldE9wdGlvbmFsRmxvYXQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbERvdWJsZSgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbERvdWJsZShvdGhlci5nZXRPcHRpb25hbERvdWJsZSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsQm9vbCgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEJvb2wob3RoZXIuZ2V0T3B0aW9uYWxCb29sKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxTdHJpbmcoKSkgewogICAgICAgICAgb3B0aW9uYWxTdHJpbmdfID0gb3RoZXIub3B0aW9uYWxTdHJpbmdfOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEJ5dGVzKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsQnl0ZXMob3RoZXIuZ2V0T3B0aW9uYWxCeXRlcygpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbEdyb3VwKG90aGVyLmdldE9wdGlvbmFsR3JvdXAoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbE5lc3RlZE1lc3NhZ2Uob3RoZXIuZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpKSB7CiAgICAgICAgICBtZXJnZU9wdGlvbmFsRm9yZWlnbk1lc3NhZ2Uob3RoZXIuZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsSW1wb3J0TWVzc2FnZSgpKSB7CiAgICAgICAgICBtZXJnZU9wdGlvbmFsSW1wb3J0TWVzc2FnZShvdGhlci5nZXRPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbE5lc3RlZEVudW0oKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxOZXN0ZWRFbnVtKG90aGVyLmdldE9wdGlvbmFsTmVzdGVkRW51bSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsRm9yZWlnbkVudW0oKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxGb3JlaWduRW51bShvdGhlci5nZXRPcHRpb25hbEZvcmVpZ25FbnVtKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxJbXBvcnRFbnVtKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsSW1wb3J0RW51bShvdGhlci5nZXRPcHRpb25hbEltcG9ydEVudW0oKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbFN0cmluZ1BpZWNlKCkpIHsKICAgICAgICAgIG9wdGlvbmFsU3RyaW5nUGllY2VfID0gb3RoZXIub3B0aW9uYWxTdHJpbmdQaWVjZV87CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDA0MDAwMDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsQ29yZCgpKSB7CiAgICAgICAgICBvcHRpb25hbENvcmRfID0gb3RoZXIub3B0aW9uYWxDb3JkXzsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDgwMDAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkpIHsKICAgICAgICAgIG1lcmdlT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKG90aGVyLmdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsTGF6eU1lc3NhZ2UoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbExhenlNZXNzYWdlKG90aGVyLmdldE9wdGlvbmFsTGF6eU1lc3NhZ2UoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSgpKSB7CiAgICAgICAgICBtZXJnZU9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKG90aGVyLmdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEludDMyXyA9IG90aGVyLnJlcGVhdGVkSW50MzJfOwogICAgICAgICAgICByZXBlYXRlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwODAwMDAwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkQWxsKG90aGVyLnJlcGVhdGVkSW50MzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkSW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkSW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEludDY0XyA9IG90aGVyLnJlcGVhdGVkSW50NjRfOwogICAgICAgICAgICByZXBlYXRlZEludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgxMDAwMDAwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQ2NF8uYWRkQWxsKG90aGVyLnJlcGVhdGVkSW50NjRfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkVWludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZFVpbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkVWludDMyXyA9IG90aGVyLnJlcGVhdGVkVWludDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDIwMDAwMDAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRVaW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRVaW50MzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZFVpbnQzMl8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRVaW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkVWludDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRVaW50NjRfID0gb3RoZXIucmVwZWF0ZWRVaW50NjRfOwogICAgICAgICAgICByZXBlYXRlZFVpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4NDAwMDAwMDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFVpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZFVpbnQ2NF8uYWRkQWxsKG90aGVyLnJlcGVhdGVkVWludDY0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZFNpbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRTaW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZFNpbnQzMl8gPSBvdGhlci5yZXBlYXRlZFNpbnQzMl87CiAgICAgICAgICAgIHJlcGVhdGVkU2ludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHg4MDAwMDAwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkU2ludDMyXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRTaW50MzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkU2ludDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZFNpbnQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkU2ludDY0XyA9IG90aGVyLnJlcGVhdGVkU2ludDY0XzsKICAgICAgICAgICAgcmVwZWF0ZWRTaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRTaW50NjRfLmFkZEFsbChvdGhlci5yZXBlYXRlZFNpbnQ2NF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRGaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEZpeGVkMzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfID0gb3RoZXIucmVwZWF0ZWRGaXhlZDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZEZpeGVkMzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkRml4ZWQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRGaXhlZDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDY0XyA9IG90aGVyLnJlcGVhdGVkRml4ZWQ2NF87CiAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDY0Xy5hZGRBbGwob3RoZXIucmVwZWF0ZWRGaXhlZDY0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZFNmaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZFNmaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRTZml4ZWQzMl8gPSBvdGhlci5yZXBlYXRlZFNmaXhlZDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRTZml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFNmaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkMzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZFNmaXhlZDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZFNmaXhlZDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZFNmaXhlZDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRTZml4ZWQ2NF8gPSBvdGhlci5yZXBlYXRlZFNmaXhlZDY0XzsKICAgICAgICAgICAgcmVwZWF0ZWRTZml4ZWQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkNjRfLmFkZEFsbChvdGhlci5yZXBlYXRlZFNmaXhlZDY0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEZsb2F0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEZsb2F0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRGbG9hdF8gPSBvdGhlci5yZXBlYXRlZEZsb2F0XzsKICAgICAgICAgICAgcmVwZWF0ZWRGbG9hdF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZsb2F0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkRmxvYXRfLmFkZEFsbChvdGhlci5yZXBlYXRlZEZsb2F0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZERvdWJsZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWREb3VibGVfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZERvdWJsZV8gPSBvdGhlci5yZXBlYXRlZERvdWJsZV87CiAgICAgICAgICAgIHJlcGVhdGVkRG91YmxlXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDA0MDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRG91YmxlSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkRG91YmxlXy5hZGRBbGwob3RoZXIucmVwZWF0ZWREb3VibGVfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkQm9vbF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRCb29sXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRCb29sXyA9IG90aGVyLnJlcGVhdGVkQm9vbF87CiAgICAgICAgICAgIHJlcGVhdGVkQm9vbF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEJvb2xJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRCb29sXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRCb29sXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZFN0cmluZ18uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRTdHJpbmdfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZFN0cmluZ18gPSBvdGhlci5yZXBlYXRlZFN0cmluZ187CiAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDEwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkU3RyaW5nXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRTdHJpbmdfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkQnl0ZXNfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkQnl0ZXNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEJ5dGVzXyA9IG90aGVyLnJlcGVhdGVkQnl0ZXNfOwogICAgICAgICAgICByZXBlYXRlZEJ5dGVzXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAwMDIwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQnl0ZXNJc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRCeXRlc18uYWRkQWxsKG90aGVyLnJlcGVhdGVkQnl0ZXNfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRHcm91cF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IG90aGVyLnJlcGVhdGVkR3JvdXBfOwogICAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAwNDAwKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8uYWRkQWxsKG90aGVyLnJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEdyb3VwXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBvdGhlci5yZXBlYXRlZEdyb3VwXzsKICAgICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDQwMCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLnJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfID0gb3RoZXIucmVwZWF0ZWROZXN0ZWRNZXNzYWdlXzsKICAgICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDgwMCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWROZXN0ZWRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5hZGRBbGwob3RoZXIucmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXyA9IG90aGVyLnJlcGVhdGVkTmVzdGVkTWVzc2FnZV87CiAgICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDA4MDApOwogICAgICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyhvdGhlci5yZXBlYXRlZE5lc3RlZE1lc3NhZ2VfKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IG90aGVyLnJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfOwogICAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAxMDAwKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uYWRkQWxsKG90aGVyLnJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8gPSBvdGhlci5yZXBlYXRlZEZvcmVpZ25NZXNzYWdlXzsKICAgICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMTAwMCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLnJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEltcG9ydE1lc3NhZ2VfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gb3RoZXIucmVwZWF0ZWRJbXBvcnRNZXNzYWdlXzsKICAgICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMjAwMCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyA9IG90aGVyLnJlcGVhdGVkSW1wb3J0TWVzc2FnZV87CiAgICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDIwMDApOwogICAgICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyhvdGhlci5yZXBlYXRlZEltcG9ydE1lc3NhZ2VfKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkTmVzdGVkRW51bV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRFbnVtXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWROZXN0ZWRFbnVtXyA9IG90aGVyLnJlcGVhdGVkTmVzdGVkRW51bV87CiAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDA0MDAwKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkRW51bUlzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fLmFkZEFsbChvdGhlci5yZXBlYXRlZE5lc3RlZEVudW1fKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkRm9yZWlnbkVudW1fLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbkVudW1fLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEZvcmVpZ25FbnVtXyA9IG90aGVyLnJlcGVhdGVkRm9yZWlnbkVudW1fOwogICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwODAwMCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25FbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbkVudW1fLmFkZEFsbChvdGhlci5yZXBlYXRlZEZvcmVpZ25FbnVtXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEltcG9ydEVudW1fLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0RW51bV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkSW1wb3J0RW51bV8gPSBvdGhlci5yZXBlYXRlZEltcG9ydEVudW1fOwogICAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAxMDAwMCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydEVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgcmVwZWF0ZWRJbXBvcnRFbnVtXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRJbXBvcnRFbnVtXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZFN0cmluZ1BpZWNlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZFN0cmluZ1BpZWNlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRTdHJpbmdQaWVjZV8gPSBvdGhlci5yZXBlYXRlZFN0cmluZ1BpZWNlXzsKICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDIwMDAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTdHJpbmdQaWVjZUlzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZFN0cmluZ1BpZWNlXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRTdHJpbmdQaWVjZV8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRDb3JkXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZENvcmRfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZENvcmRfID0gb3RoZXIucmVwZWF0ZWRDb3JkXzsKICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDQwMDAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRDb3JkSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkQ29yZF8uYWRkQWxsKG90aGVyLnJlcGVhdGVkQ29yZF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZExhenlNZXNzYWdlXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gb3RoZXIucmVwZWF0ZWRMYXp5TWVzc2FnZV87CiAgICAgICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwODAwMDApOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTGF6eU1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRMYXp5TWVzc2FnZV8pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkTGF6eU1lc3NhZ2VfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXyA9IG90aGVyLnJlcGVhdGVkTGF6eU1lc3NhZ2VfOwogICAgICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDgwMDAwKTsKICAgICAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMgPwogICAgICAgICAgICAgICAgICAgZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIucmVwZWF0ZWRMYXp5TWVzc2FnZV8pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0SW50MzIoKSkgewogICAgICAgICAgc2V0RGVmYXVsdEludDMyKG90aGVyLmdldERlZmF1bHRJbnQzMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRJbnQ2NCgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0SW50NjQob3RoZXIuZ2V0RGVmYXVsdEludDY0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdFVpbnQzMigpKSB7CiAgICAgICAgICBzZXREZWZhdWx0VWludDMyKG90aGVyLmdldERlZmF1bHRVaW50MzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0VWludDY0KCkpIHsKICAgICAgICAgIHNldERlZmF1bHRVaW50NjQob3RoZXIuZ2V0RGVmYXVsdFVpbnQ2NCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRTaW50MzIoKSkgewogICAgICAgICAgc2V0RGVmYXVsdFNpbnQzMihvdGhlci5nZXREZWZhdWx0U2ludDMyKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdFNpbnQ2NCgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0U2ludDY0KG90aGVyLmdldERlZmF1bHRTaW50NjQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0Rml4ZWQzMigpKSB7CiAgICAgICAgICBzZXREZWZhdWx0Rml4ZWQzMihvdGhlci5nZXREZWZhdWx0Rml4ZWQzMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRGaXhlZDY0KCkpIHsKICAgICAgICAgIHNldERlZmF1bHRGaXhlZDY0KG90aGVyLmdldERlZmF1bHRGaXhlZDY0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdFNmaXhlZDMyKCkpIHsKICAgICAgICAgIHNldERlZmF1bHRTZml4ZWQzMihvdGhlci5nZXREZWZhdWx0U2ZpeGVkMzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0U2ZpeGVkNjQoKSkgewogICAgICAgICAgc2V0RGVmYXVsdFNmaXhlZDY0KG90aGVyLmdldERlZmF1bHRTZml4ZWQ2NCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRGbG9hdCgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0RmxvYXQob3RoZXIuZ2V0RGVmYXVsdEZsb2F0KCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdERvdWJsZSgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0RG91YmxlKG90aGVyLmdldERlZmF1bHREb3VibGUoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0Qm9vbCgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0Qm9vbChvdGhlci5nZXREZWZhdWx0Qm9vbCgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRTdHJpbmcoKSkgewogICAgICAgICAgZGVmYXVsdFN0cmluZ18gPSBvdGhlci5kZWZhdWx0U3RyaW5nXzsKICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdEJ5dGVzKCkpIHsKICAgICAgICAgIHNldERlZmF1bHRCeXRlcyhvdGhlci5nZXREZWZhdWx0Qnl0ZXMoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0TmVzdGVkRW51bSgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0TmVzdGVkRW51bShvdGhlci5nZXREZWZhdWx0TmVzdGVkRW51bSgpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRGb3JlaWduRW51bSgpKSB7CiAgICAgICAgICBzZXREZWZhdWx0Rm9yZWlnbkVudW0ob3RoZXIuZ2V0RGVmYXVsdEZvcmVpZ25FbnVtKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVmYXVsdEltcG9ydEVudW0oKSkgewogICAgICAgICAgc2V0RGVmYXVsdEltcG9ydEVudW0ob3RoZXIuZ2V0RGVmYXVsdEltcG9ydEVudW0oKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZWZhdWx0U3RyaW5nUGllY2UoKSkgewogICAgICAgICAgZGVmYXVsdFN0cmluZ1BpZWNlXyA9IG90aGVyLmRlZmF1bHRTdHJpbmdQaWVjZV87CiAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlZmF1bHRDb3JkKCkpIHsKICAgICAgICAgIGRlZmF1bHRDb3JkXyA9IG90aGVyLmRlZmF1bHRDb3JkXzsKICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDA4MDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVjZXB0aXZlbHlOYW1lZExpc3QoKSkgewogICAgICAgICAgc2V0RGVjZXB0aXZlbHlOYW1lZExpc3Qob3RoZXIuZ2V0RGVjZXB0aXZlbHlOYW1lZExpc3QoKSk7CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAob3RoZXIuZ2V0T25lb2ZGaWVsZENhc2UoKSkgewogICAgICAgICAgY2FzZSBPTkVPRl9VSU5UMzI6IHsKICAgICAgICAgICAgc2V0T25lb2ZVaW50MzIob3RoZXIuZ2V0T25lb2ZVaW50MzIoKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9ORVNURURfTUVTU0FHRTogewogICAgICAgICAgICBtZXJnZU9uZW9mTmVzdGVkTWVzc2FnZShvdGhlci5nZXRPbmVvZk5lc3RlZE1lc3NhZ2UoKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9TVFJJTkc6IHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTEzOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG90aGVyLm9uZW9mRmllbGRfOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX0JZVEVTOiB7CiAgICAgICAgICAgIHNldE9uZW9mQnl0ZXMob3RoZXIuZ2V0T25lb2ZCeXRlcygpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX0xBWllfTkVTVEVEX01FU1NBR0U6IHsKICAgICAgICAgICAgbWVyZ2VPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKG90aGVyLmdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9ORVNURURfTUVTU0FHRTI6IHsKICAgICAgICAgICAgbWVyZ2VPbmVvZk5lc3RlZE1lc3NhZ2UyKG90aGVyLmdldE9uZW9mTmVzdGVkTWVzc2FnZTIoKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRkZJRUxEX05PVF9TRVQ6IHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgODogewogICAgICAgICAgICAgICAgb3B0aW9uYWxJbnQzMl8gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4CiAgICAgICAgICAgICAgY2FzZSAxNjogewogICAgICAgICAgICAgICAgb3B0aW9uYWxJbnQ2NF8gPSBpbnB1dC5yZWFkSW50NjQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNgogICAgICAgICAgICAgIGNhc2UgMjQ6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsVWludDMyXyA9IGlucHV0LnJlYWRVSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyNAogICAgICAgICAgICAgIGNhc2UgMzI6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsVWludDY0XyA9IGlucHV0LnJlYWRVSW50NjQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMgogICAgICAgICAgICAgIGNhc2UgNDA6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsU2ludDMyXyA9IGlucHV0LnJlYWRTSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0MAogICAgICAgICAgICAgIGNhc2UgNDg6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsU2ludDY0XyA9IGlucHV0LnJlYWRTSW50NjQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0OAogICAgICAgICAgICAgIGNhc2UgNjE6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsRml4ZWQzMl8gPSBpbnB1dC5yZWFkRml4ZWQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDYxCiAgICAgICAgICAgICAgY2FzZSA2NTogewogICAgICAgICAgICAgICAgb3B0aW9uYWxGaXhlZDY0XyA9IGlucHV0LnJlYWRGaXhlZDY0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNjUKICAgICAgICAgICAgICBjYXNlIDc3OiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbFNmaXhlZDMyXyA9IGlucHV0LnJlYWRTRml4ZWQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc3CiAgICAgICAgICAgICAgY2FzZSA4MTogewogICAgICAgICAgICAgICAgb3B0aW9uYWxTZml4ZWQ2NF8gPSBpbnB1dC5yZWFkU0ZpeGVkNjQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4MQogICAgICAgICAgICAgIGNhc2UgOTM6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsRmxvYXRfID0gaW5wdXQucmVhZEZsb2F0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTMKICAgICAgICAgICAgICBjYXNlIDk3OiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbERvdWJsZV8gPSBpbnB1dC5yZWFkRG91YmxlKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTcKICAgICAgICAgICAgICBjYXNlIDEwNDogewogICAgICAgICAgICAgICAgb3B0aW9uYWxCb29sXyA9IGlucHV0LnJlYWRCb29sKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTA0CiAgICAgICAgICAgICAgY2FzZSAxMTQ6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDExNAogICAgICAgICAgICAgIGNhc2UgMTIyOiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbEJ5dGVzXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEyMgogICAgICAgICAgICAgIGNhc2UgMTMxOiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoMTYsCiAgICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTMxCiAgICAgICAgICAgICAgY2FzZSAxNDY6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMTAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTQ2CiAgICAgICAgICAgICAgY2FzZSAxNTQ6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDIwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE1NAogICAgICAgICAgICAgIGNhc2UgMTYyOiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEltcG9ydE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDQwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2MgogICAgICAgICAgICAgIGNhc2UgMTY4OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoMjEsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBvcHRpb25hbE5lc3RlZEVudW1fID0gdG1wUmF3OwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwODAwMDA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTY4CiAgICAgICAgICAgICAgY2FzZSAxNzY6IHsKICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCgyMiwgdG1wUmF3KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbkVudW1fID0gdG1wUmF3OwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAxMDAwMDA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTc2CiAgICAgICAgICAgICAgY2FzZSAxODQ6IHsKICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoMjMsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBvcHRpb25hbEltcG9ydEVudW1fID0gdG1wUmF3OwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAyMDAwMDA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTg0CiAgICAgICAgICAgICAgY2FzZSAxOTQ6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsU3RyaW5nUGllY2VfID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDA0MDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTk0CiAgICAgICAgICAgICAgY2FzZSAyMDI6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsQ29yZF8gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDgwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyMDIKICAgICAgICAgICAgICBjYXNlIDIxMDogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMTAwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyMTAKICAgICAgICAgICAgICBjYXNlIDIxODogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDIwMDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjE4CiAgICAgICAgICAgICAgY2FzZSAyMjY6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwNDAwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyMjYKICAgICAgICAgICAgICBjYXNlIDI0ODogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyNDgKICAgICAgICAgICAgICBjYXNlIDI1MDogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludChpbnB1dC5yZWFkSW50MzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjUwCiAgICAgICAgICAgICAgY2FzZSAyNTY6IHsKICAgICAgICAgICAgICAgIGxvbmcgdiA9IGlucHV0LnJlYWRJbnQ2NCgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRJbnQ2NF8uYWRkTG9uZyh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyNTYKICAgICAgICAgICAgICBjYXNlIDI1ODogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50NjRfLmFkZExvbmcoaW5wdXQucmVhZEludDY0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI1OAogICAgICAgICAgICAgIGNhc2UgMjY0OiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRVSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZFVpbnQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI2NAogICAgICAgICAgICAgIGNhc2UgMjY2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkVWludDMyXy5hZGRJbnQoaW5wdXQucmVhZFVJbnQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyNjYKICAgICAgICAgICAgICBjYXNlIDI3MjogewogICAgICAgICAgICAgICAgbG9uZyB2ID0gaW5wdXQucmVhZFVJbnQ2NCgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRVaW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkVWludDY0Xy5hZGRMb25nKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI3MgogICAgICAgICAgICAgIGNhc2UgMjc0OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkVWludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkVWludDY0Xy5hZGRMb25nKGlucHV0LnJlYWRVSW50NjQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjc0CiAgICAgICAgICAgICAgY2FzZSAyODA6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZFNJbnQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTaW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkU2ludDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjgwCiAgICAgICAgICAgICAgY2FzZSAyODI6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTaW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRTaW50MzJfLmFkZEludChpbnB1dC5yZWFkU0ludDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI4MgogICAgICAgICAgICAgIGNhc2UgMjg4OiB7CiAgICAgICAgICAgICAgICBsb25nIHYgPSBpbnB1dC5yZWFkU0ludDY0KCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFNpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRTaW50NjRfLmFkZExvbmcodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjg4CiAgICAgICAgICAgICAgY2FzZSAyOTA6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRTaW50NjRfLmFkZExvbmcoaW5wdXQucmVhZFNJbnQ2NCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyOTAKICAgICAgICAgICAgICBjYXNlIDMwMTogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkRml4ZWQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMDEKICAgICAgICAgICAgICBjYXNlIDI5ODogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZShhbGxvYyAvIDQpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEludChpbnB1dC5yZWFkRml4ZWQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAyOTgKICAgICAgICAgICAgICBjYXNlIDMwNTogewogICAgICAgICAgICAgICAgbG9uZyB2ID0gaW5wdXQucmVhZEZpeGVkNjQoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDY0Xy5hZGRMb25nKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDMwNQogICAgICAgICAgICAgIGNhc2UgMzA2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDY0SXNNdXRhYmxlKGFsbG9jIC8gOCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQ2NF8uYWRkTG9uZyhpbnB1dC5yZWFkRml4ZWQ2NCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMDYKICAgICAgICAgICAgICBjYXNlIDMxNzogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkU0ZpeGVkMzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU2ZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkU2ZpeGVkMzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMTcKICAgICAgICAgICAgICBjYXNlIDMxNDogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkU2ZpeGVkMzJJc011dGFibGUoYWxsb2MgLyA0KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRTZml4ZWQzMl8uYWRkSW50KGlucHV0LnJlYWRTRml4ZWQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMTQKICAgICAgICAgICAgICBjYXNlIDMyMTogewogICAgICAgICAgICAgICAgbG9uZyB2ID0gaW5wdXQucmVhZFNGaXhlZDY0KCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFNmaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZFNmaXhlZDY0Xy5hZGRMb25nKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDMyMQogICAgICAgICAgICAgIGNhc2UgMzIyOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTZml4ZWQ2NElzTXV0YWJsZShhbGxvYyAvIDgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZFNmaXhlZDY0Xy5hZGRMb25nKGlucHV0LnJlYWRTRml4ZWQ2NCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMjIKICAgICAgICAgICAgICBjYXNlIDMzMzogewogICAgICAgICAgICAgICAgZmxvYXQgdiA9IGlucHV0LnJlYWRGbG9hdCgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGbG9hdElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRGbG9hdF8uYWRkRmxvYXQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzMzCiAgICAgICAgICAgICAgY2FzZSAzMzA6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZsb2F0SXNNdXRhYmxlKGFsbG9jIC8gNCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkRmxvYXRfLmFkZEZsb2F0KGlucHV0LnJlYWRGbG9hdCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMzAKICAgICAgICAgICAgICBjYXNlIDMzNzogewogICAgICAgICAgICAgICAgZG91YmxlIHYgPSBpbnB1dC5yZWFkRG91YmxlKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZERvdWJsZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWREb3VibGVfLmFkZERvdWJsZSh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMzcKICAgICAgICAgICAgICBjYXNlIDMzODogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRG91YmxlSXNNdXRhYmxlKGFsbG9jIC8gOCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkRG91YmxlXy5hZGREb3VibGUoaW5wdXQucmVhZERvdWJsZSgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzMzgKICAgICAgICAgICAgICBjYXNlIDM0NDogewogICAgICAgICAgICAgICAgYm9vbGVhbiB2ID0gaW5wdXQucmVhZEJvb2woKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQm9vbElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRCb29sXy5hZGRCb29sZWFuKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM0NAogICAgICAgICAgICAgIGNhc2UgMzQ2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRCb29sSXNNdXRhYmxlKGFsbG9jIC8gMSk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkQm9vbF8uYWRkQm9vbGVhbihpbnB1dC5yZWFkQm9vbCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzNDYKICAgICAgICAgICAgICBjYXNlIDM1NDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZFN0cmluZ0lzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRTdHJpbmdfLmFkZChicyk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzU0CiAgICAgICAgICAgICAgY2FzZSAzNjI6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2ID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEJ5dGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICByZXBlYXRlZEJ5dGVzXy5hZGQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzYyCiAgICAgICAgICAgICAgY2FzZSAzNzE6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cCBtID0KICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoNDYsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUmVwZWF0ZWRHcm91cC5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBfLmFkZChtKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM3MQogICAgICAgICAgICAgIGNhc2UgMzg2OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgbSA9CiAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLmFkZChtKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UobSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzg2CiAgICAgICAgICAgICAgY2FzZSAzOTQ6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBtID0KICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLlBBUlNFUiwKICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uYWRkKG0pOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UobSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzk0CiAgICAgICAgICAgICAgY2FzZSA0MDI6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLmFkZChtKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UobSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDAyCiAgICAgICAgICAgICAgY2FzZSA0MDg6IHsKICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg1MSwgdG1wUmF3KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkRW51bUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fLmFkZCh0bXBSYXcpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQwOAogICAgICAgICAgICAgIGNhc2UgNDEwOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgb2xkTGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIHdoaWxlKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg1MSwgdG1wUmF3KTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZEVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fLmFkZCh0bXBSYXcpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChvbGRMaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDEwCiAgICAgICAgICAgICAgY2FzZSA0MTY6IHsKICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg1MiwgdG1wUmF3KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbkVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8uYWRkKHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDE2CiAgICAgICAgICAgICAgY2FzZSA0MTg6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBvbGRMaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgd2hpbGUoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDUyLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbkVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgICByZXBlYXRlZEZvcmVpZ25FbnVtXy5hZGQodG1wUmF3KTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQob2xkTGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQxOAogICAgICAgICAgICAgIGNhc2UgNDI0OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDUzLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkSW1wb3J0RW51bV8uYWRkKHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDI0CiAgICAgICAgICAgICAgY2FzZSA0MjY6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBvbGRMaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgd2hpbGUoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg1MywgdG1wUmF3KTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydEVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydEVudW1fLmFkZCh0bXBSYXcpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChvbGRMaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDI2CiAgICAgICAgICAgICAgY2FzZSA0MzQ6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRTdHJpbmdQaWVjZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcmVwZWF0ZWRTdHJpbmdQaWVjZV8uYWRkKGJzKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0MzQKICAgICAgICAgICAgICBjYXNlIDQ0MjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZENvcmRJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkQ29yZF8uYWRkKGJzKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0NDIKICAgICAgICAgICAgICBjYXNlIDQ1ODogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG0gPQogICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRMYXp5TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXy5hZGQobSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZShtKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0NTgKICAgICAgICAgICAgICBjYXNlIDQ4ODogewogICAgICAgICAgICAgICAgZGVmYXVsdEludDMyXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMTAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDQ4OAogICAgICAgICAgICAgIGNhc2UgNDk2OiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0SW50NjRfID0gaW5wdXQucmVhZEludDY0KCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAyMDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDk2CiAgICAgICAgICAgICAgY2FzZSA1MDQ6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRVaW50MzJfID0gaW5wdXQucmVhZFVJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwNDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDUwNAogICAgICAgICAgICAgIGNhc2UgNTEyOiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0VWludDY0XyA9IGlucHV0LnJlYWRVSW50NjQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDgwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1MTIKICAgICAgICAgICAgICBjYXNlIDUyMDogewogICAgICAgICAgICAgICAgZGVmYXVsdFNpbnQzMl8gPSBpbnB1dC5yZWFkU0ludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDEwMDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTIwCiAgICAgICAgICAgICAgY2FzZSA1Mjg6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRTaW50NjRfID0gaW5wdXQucmVhZFNJbnQ2NCgpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDAyMDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDUyOAogICAgICAgICAgICAgIGNhc2UgNTQxOiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0Rml4ZWQzMl8gPSBpbnB1dC5yZWFkRml4ZWQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDA0MDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDU0MQogICAgICAgICAgICAgIGNhc2UgNTQ1OiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0Rml4ZWQ2NF8gPSBpbnB1dC5yZWFkRml4ZWQ2NCgpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDA4MDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDU0NQogICAgICAgICAgICAgIGNhc2UgNTU3OiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0U2ZpeGVkMzJfID0gaW5wdXQucmVhZFNGaXhlZDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MTAwMDAwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTU3CiAgICAgICAgICAgICAgY2FzZSA1NjE6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRTZml4ZWQ2NF8gPSBpbnB1dC5yZWFkU0ZpeGVkNjQoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgyMDAwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1NjEKICAgICAgICAgICAgICBjYXNlIDU3MzogewogICAgICAgICAgICAgICAgZGVmYXVsdEZsb2F0XyA9IGlucHV0LnJlYWRGbG9hdCgpOwogICAgICAgICAgICAgICAgYml0RmllbGQxXyB8PSAweDQwMDAwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDU3MwogICAgICAgICAgICAgIGNhc2UgNTc3OiB7CiAgICAgICAgICAgICAgICBkZWZhdWx0RG91YmxlXyA9IGlucHV0LnJlYWREb3VibGUoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHg4MDAwMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1NzcKICAgICAgICAgICAgICBjYXNlIDU4NDogewogICAgICAgICAgICAgICAgZGVmYXVsdEJvb2xfID0gaW5wdXQucmVhZEJvb2woKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1ODQKICAgICAgICAgICAgICBjYXNlIDU5NDogewogICAgICAgICAgICAgICAgZGVmYXVsdFN0cmluZ18gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1OTQKICAgICAgICAgICAgICBjYXNlIDYwMjogewogICAgICAgICAgICAgICAgZGVmYXVsdEJ5dGVzXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDYwMgogICAgICAgICAgICAgIGNhc2UgNjQ4OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLmZvck51bWJlcih0bXBSYXcpOwogICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duVmFyaW50RmllbGQoODEsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBkZWZhdWx0TmVzdGVkRW51bV8gPSB0bXBSYXc7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAwODsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA2NDgKICAgICAgICAgICAgICBjYXNlIDY1NjogewogICAgICAgICAgICAgICAgaW50IHRtcFJhdyA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDgyLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZGVmYXVsdEZvcmVpZ25FbnVtXyA9IHRtcFJhdzsKICAgICAgICAgICAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDEwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDY1NgogICAgICAgICAgICAgIGNhc2UgNjY0OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDgzLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZGVmYXVsdEltcG9ydEVudW1fID0gdG1wUmF3OwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNjY0CiAgICAgICAgICAgICAgY2FzZSA2NzQ6IHsKICAgICAgICAgICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDA0MDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA2NzQKICAgICAgICAgICAgICBjYXNlIDY4MjogewogICAgICAgICAgICAgICAgZGVmYXVsdENvcmRfID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNjgyCiAgICAgICAgICAgICAgY2FzZSA4ODg6IHsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gaW5wdXQucmVhZFVJbnQzMigpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTExOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDg4OAogICAgICAgICAgICAgIGNhc2UgODk4OiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPbmVvZk5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTEyOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDg5OAogICAgICAgICAgICAgIGNhc2UgOTA2OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMzsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYnM7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTA2CiAgICAgICAgICAgICAgY2FzZSA5MTQ6IHsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTQ7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTE0CiAgICAgICAgICAgICAgY2FzZSA5MjI6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTE1OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDkyMgogICAgICAgICAgICAgIGNhc2UgOTI4OiB7CiAgICAgICAgICAgICAgICBkZWNlcHRpdmVseU5hbWVkTGlzdF8gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwNDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA5MjgKICAgICAgICAgICAgICBjYXNlIDkzODogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlMkZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTc7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTM4CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgcHJpdmF0ZSBqYXZhLmxhbmcuT2JqZWN0IG9uZW9mRmllbGRfOwogICAgICBwdWJsaWMgT25lb2ZGaWVsZENhc2UKICAgICAgICAgIGdldE9uZW9mRmllbGRDYXNlKCkgewogICAgICAgIHJldHVybiBPbmVvZkZpZWxkQ2FzZS5mb3JOdW1iZXIoCiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZGaWVsZCgpIHsKICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQxXzsKICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQyXzsKCiAgICAgIHByaXZhdGUgaW50IG9wdGlvbmFsSW50MzJfIDsKICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIFNpbmd1bGFyCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBvcHRpb25hbF9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEludDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogU2luZ3VsYXIKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW50MzIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0T3B0aW9uYWxJbnQzMigpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxJbnQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIFNpbmd1bGFyCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBvcHRpb25hbF9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsSW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBvcHRpb25hbEludDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogU2luZ3VsYXIKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxJbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgb3B0aW9uYWxJbnQzMl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGxvbmcgb3B0aW9uYWxJbnQ2NF8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50NjQgb3B0aW9uYWxfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEludDY0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxJbnQ2NCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IG9wdGlvbmFsX2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW50NjQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE9wdGlvbmFsSW50NjQoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsSW50NjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBvcHRpb25hbF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsSW50NjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxJbnQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IG9wdGlvbmFsX2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxJbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgb3B0aW9uYWxJbnQ2NF8gPSAwTDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxVaW50MzJfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQzMiBvcHRpb25hbF91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFVpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsVWludDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIG9wdGlvbmFsX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFVpbnQzMi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRPcHRpb25hbFVpbnQzMigpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxVaW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgb3B0aW9uYWxfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxVaW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFVpbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxVaW50MzJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgb3B0aW9uYWxfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxVaW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgIG9wdGlvbmFsVWludDMyXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgbG9uZyBvcHRpb25hbFVpbnQ2NF8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IG9wdGlvbmFsX3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsVWludDY0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxVaW50NjQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50NjQgb3B0aW9uYWxfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsVWludDY0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRPcHRpb25hbFVpbnQ2NCgpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxVaW50NjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50NjQgb3B0aW9uYWxfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxVaW50NjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFVpbnQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsVWludDY0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IG9wdGlvbmFsX3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsVWludDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICBvcHRpb25hbFVpbnQ2NF8gPSAwTDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxTaW50MzJfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQzMiBvcHRpb25hbF9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFNpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU2ludDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIG9wdGlvbmFsX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFNpbnQzMi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRPcHRpb25hbFNpbnQzMigpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxTaW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgb3B0aW9uYWxfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxTaW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFNpbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxTaW50MzJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgb3B0aW9uYWxfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxTaW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgIG9wdGlvbmFsU2ludDMyXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgbG9uZyBvcHRpb25hbFNpbnQ2NF8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IG9wdGlvbmFsX3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU2ludDY0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxTaW50NjQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50NjQgb3B0aW9uYWxfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU2ludDY0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRPcHRpb25hbFNpbnQ2NCgpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxTaW50NjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50NjQgb3B0aW9uYWxfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxTaW50NjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFNpbnQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsU2ludDY0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDY0IG9wdGlvbmFsX3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsU2ludDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDIwKTsKICAgICAgICBvcHRpb25hbFNpbnQ2NF8gPSAwTDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxGaXhlZDMyXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIG9wdGlvbmFsX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZpeGVkMzIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwNDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIG9wdGlvbmFsX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxGaXhlZDMyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE9wdGlvbmFsRml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxGaXhlZDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBvcHRpb25hbF9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxGaXhlZDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxGaXhlZDMyKGludCB2YWx1ZSkgewoKICAgICAgICBvcHRpb25hbEZpeGVkMzJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIG9wdGlvbmFsX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEZpeGVkMzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwNDApOwogICAgICAgIG9wdGlvbmFsRml4ZWQzMl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGxvbmcgb3B0aW9uYWxGaXhlZDY0XyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IG9wdGlvbmFsX2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEZpeGVkNjQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZpeGVkNjQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwODApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IG9wdGlvbmFsX2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxGaXhlZDY0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRPcHRpb25hbEZpeGVkNjQoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsRml4ZWQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgb3B0aW9uYWxfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsRml4ZWQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsRml4ZWQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIG9wdGlvbmFsRml4ZWQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgb3B0aW9uYWxfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsRml4ZWQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA4MCk7CiAgICAgICAgb3B0aW9uYWxGaXhlZDY0XyA9IDBMOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBvcHRpb25hbFNmaXhlZDMyXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQzMiBvcHRpb25hbF9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU2ZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFNmaXhlZDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMTAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgb3B0aW9uYWxfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTZml4ZWQzMi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRPcHRpb25hbFNmaXhlZDMyKCkgewogICAgICAgIHJldHVybiBvcHRpb25hbFNmaXhlZDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgb3B0aW9uYWxfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbFNmaXhlZDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTZml4ZWQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxTZml4ZWQzMl8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIG9wdGlvbmFsX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxTZml4ZWQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDEwMCk7CiAgICAgICAgb3B0aW9uYWxTZml4ZWQzMl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGxvbmcgb3B0aW9uYWxTZml4ZWQ2NF8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgb3B0aW9uYWxfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTZml4ZWQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU2ZpeGVkNjQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAyMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzZml4ZWQ2NCBvcHRpb25hbF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxTZml4ZWQ2NC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0T3B0aW9uYWxTZml4ZWQ2NCgpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxTZml4ZWQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IG9wdGlvbmFsX3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsU2ZpeGVkNjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFNmaXhlZDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxTZml4ZWQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IG9wdGlvbmFsX3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsU2ZpeGVkNjQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAyMDApOwogICAgICAgIG9wdGlvbmFsU2ZpeGVkNjRfID0gMEw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgZmxvYXQgb3B0aW9uYWxGbG9hdF8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgb3B0aW9uYWxfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxGbG9hdCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsRmxvYXQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDA0MDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmbG9hdCBvcHRpb25hbF9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxGbG9hdC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZsb2F0IGdldE9wdGlvbmFsRmxvYXQoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsRmxvYXRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmbG9hdCBvcHRpb25hbF9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbEZsb2F0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxGbG9hdChmbG9hdCB2YWx1ZSkgewoKICAgICAgICBvcHRpb25hbEZsb2F0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgb3B0aW9uYWxfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxGbG9hdCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDQwMCk7CiAgICAgICAgb3B0aW9uYWxGbG9hdF8gPSAwRjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBkb3VibGUgb3B0aW9uYWxEb3VibGVfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBvcHRpb25hbF9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxEb3VibGUgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbERvdWJsZSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDgwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBvcHRpb25hbF9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRG91YmxlLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZG91YmxlIGdldE9wdGlvbmFsRG91YmxlKCkgewogICAgICAgIHJldHVybiBvcHRpb25hbERvdWJsZV87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBvcHRpb25hbF9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxEb3VibGUgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbERvdWJsZShkb3VibGUgdmFsdWUpIHsKCiAgICAgICAgb3B0aW9uYWxEb3VibGVfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBkb3VibGUgb3B0aW9uYWxfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsRG91YmxlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwODAwKTsKICAgICAgICBvcHRpb25hbERvdWJsZV8gPSAwRDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBib29sZWFuIG9wdGlvbmFsQm9vbF8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYm9vbCBvcHRpb25hbF9ib29sID0gMTM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQm9vbCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsQm9vbCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMTAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgb3B0aW9uYWxfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxCb29sLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBnZXRPcHRpb25hbEJvb2woKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsQm9vbF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgb3B0aW9uYWxfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbEJvb2wgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEJvb2woYm9vbGVhbiB2YWx1ZSkgewoKICAgICAgICBvcHRpb25hbEJvb2xfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBib29sIG9wdGlvbmFsX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxCb29sKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAxMDAwKTsKICAgICAgICBvcHRpb25hbEJvb2xfID0gZmFsc2U7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxTdHJpbmcoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDIwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFN0cmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE9wdGlvbmFsU3RyaW5nKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxTdHJpbmdfOwogICAgICAgIGlmICghKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPQogICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgICAgb3B0aW9uYWxTdHJpbmdfID0gczsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldE9wdGlvbmFsU3RyaW5nQnl0ZXMoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ187CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGI7CiAgICAgICAgICByZXR1cm4gYjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFN0cmluZygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbFN0cmluZygpIHsKICAgICAgICBvcHRpb25hbFN0cmluZ18gPSBnZXREZWZhdWx0SW5zdGFuY2UoKS5nZXRPcHRpb25hbFN0cmluZygpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFN0cmluZ0J5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbFN0cmluZ18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDIwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIG9wdGlvbmFsQnl0ZXNfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsQnl0ZXMoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDQwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxCeXRlcy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPcHRpb25hbEJ5dGVzKCkgewogICAgICAgIHJldHVybiBvcHRpb25hbEJ5dGVzXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxCeXRlcyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsQnl0ZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbEJ5dGVzXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwNDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxCeXRlcygpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwNDAwMCk7CiAgICAgICAgb3B0aW9uYWxCeXRlc18gPSBnZXREZWZhdWx0SW5zdGFuY2UoKS5nZXRPcHRpb25hbEJ5dGVzKCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIG9wdGlvbmFsR3JvdXBfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXI+IG9wdGlvbmFsR3JvdXBCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxNiB7IC4uLiB9PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsZ3JvdXAgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwODAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxNiB7IC4uLiB9PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbGdyb3VwLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9wdGlvbmFsR3JvdXBfID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsR3JvdXAoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxHcm91cChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDA4MDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbEdyb3VwXyAhPSBudWxsICYmCiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbEdyb3VwXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsR3JvdXAoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDgwMDApOwogICAgICAgIG9wdGlvbmFsR3JvdXBfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDE2IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIgZ2V0T3B0aW9uYWxHcm91cEJ1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRPcHRpb25hbEdyb3VwRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXIgZ2V0T3B0aW9uYWxHcm91cE9yQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxHcm91cF8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxHcm91cF87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTYgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cCgpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gb3B0aW9uYWxHcm91cEJ1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbE5lc3RlZE1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDEwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsTmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMTAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2UgPSAxODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VPcHRpb25hbE5lc3RlZE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDEwMDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbE5lc3RlZE1lc3NhZ2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxOZXN0ZWRNZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDEwMDAwKTsKICAgICAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZSA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gZ2V0T3B0aW9uYWxOZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTmVzdGVkTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE5lc3RlZE1lc3NhZ2VfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsTmVzdGVkTWVzc2FnZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX25lc3RlZF9tZXNzYWdlID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbE5lc3RlZE1lc3NhZ2UoKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9wdGlvbmFsTmVzdGVkTWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gb3B0aW9uYWxOZXN0ZWRNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+IG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAyMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9tZXNzYWdlID0gMTk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEZvcmVpZ25NZXNzYWdlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGlmIChvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDIwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDIwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxGb3JlaWduTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDIwMDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyAhPSBudWxsICYmCiAgICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAyMDAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9mb3JlaWduX21lc3NhZ2UgPSAxOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMjAwMDApOwogICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9mb3JlaWduX21lc3NhZ2UgPSAxOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDIwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxGb3JlaWduTWVzc2FnZV8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxGb3JlaWduTWVzc2FnZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2FnZSA9IDE5OzwvY29kZT4KICAgICAgICovCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRPcHRpb25hbEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxGb3JlaWduTWVzc2FnZSgpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb3B0aW9uYWxGb3JlaWduTWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gb3B0aW9uYWxGb3JlaWduTWVzc2FnZUJ1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW1wb3J0TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwNDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEltcG9ydE1lc3NhZ2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlKCkgewogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEltcG9ydE1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsSW1wb3J0TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDA0MDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsSW1wb3J0TWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDA0MDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxJbXBvcnRNZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDQwMDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDQwMDAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEltcG9ydE1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwNDAwMDApOwogICAgICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlID0gMjA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwNDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9pbXBvcnRfbWVzc2FnZSA9IDIwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbEltcG9ydE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsSW1wb3J0TWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEltcG9ydE1lc3NhZ2VfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxJbXBvcnRNZXNzYWdlXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfaW1wb3J0X21lc3NhZ2UgPSAyMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T3B0aW9uYWxJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsSW1wb3J0TWVzc2FnZSgpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb3B0aW9uYWxJbXBvcnRNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbEltcG9ydE1lc3NhZ2VCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxOZXN0ZWRFbnVtXyA9IDE7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIG9wdGlvbmFsX25lc3RlZF9lbnVtID0gMjE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsTmVzdGVkRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsTmVzdGVkRW51bSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDA4MDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gb3B0aW9uYWxfbmVzdGVkX2VudW0gPSAyMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsTmVzdGVkRW51bS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBnZXRPcHRpb25hbE5lc3RlZEVudW0oKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bS5mb3JOdW1iZXIob3B0aW9uYWxOZXN0ZWRFbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLkZPTyA6IHJlc3VsdDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBvcHRpb25hbF9uZXN0ZWRfZW51bSA9IDIxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbE5lc3RlZEVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbE5lc3RlZEVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwODAwMDA7CiAgICAgICAgb3B0aW9uYWxOZXN0ZWRFbnVtXyA9IHZhbHVlLmdldE51bWJlcigpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIG9wdGlvbmFsX25lc3RlZF9lbnVtID0gMjE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsTmVzdGVkRW51bSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDA4MDAwMCk7CiAgICAgICAgb3B0aW9uYWxOZXN0ZWRFbnVtXyA9IDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IG9wdGlvbmFsRm9yZWlnbkVudW1fID0gNDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9lbnVtID0gMjI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsRm9yZWlnbkVudW0gZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEZvcmVpZ25FbnVtKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMTAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9mb3JlaWduX2VudW0gPSAyMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRm9yZWlnbkVudW0uCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgZ2V0T3B0aW9uYWxGb3JlaWduRW51bSgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcihvcHRpb25hbEZvcmVpZ25FbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLkZPUkVJR05fTElURV9GT08gOiByZXN1bHQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9lbnVtID0gMjI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsRm9yZWlnbkVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEZvcmVpZ25FbnVtKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMTAwMDAwOwogICAgICAgIG9wdGlvbmFsRm9yZWlnbkVudW1fID0gdmFsdWUuZ2V0TnVtYmVyKCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZm9yZWlnbl9lbnVtID0gMjI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsRm9yZWlnbkVudW0oKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAxMDAwMDApOwogICAgICAgIG9wdGlvbmFsRm9yZWlnbkVudW1fID0gNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgb3B0aW9uYWxJbXBvcnRFbnVtXyA9IDc7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIG9wdGlvbmFsX2ltcG9ydF9lbnVtID0gMjM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsSW1wb3J0RW51bSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW1wb3J0RW51bSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDIwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgb3B0aW9uYWxfaW1wb3J0X2VudW0gPSAyMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW1wb3J0RW51bS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIGdldE9wdGlvbmFsSW1wb3J0RW51bSgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5mb3JOdW1iZXIob3B0aW9uYWxJbXBvcnRFbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuSU1QT1JUX0xJVEVfRk9PIDogcmVzdWx0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIG9wdGlvbmFsX2ltcG9ydF9lbnVtID0gMjM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsSW1wb3J0RW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsSW1wb3J0RW51bShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMjAwMDAwOwogICAgICAgIG9wdGlvbmFsSW1wb3J0RW51bV8gPSB2YWx1ZS5nZXROdW1iZXIoKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBvcHRpb25hbF9pbXBvcnRfZW51bSA9IDIzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEltcG9ydEVudW0oKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAyMDAwMDApOwogICAgICAgIG9wdGlvbmFsSW1wb3J0RW51bV8gPSA3OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3Qgb3B0aW9uYWxTdHJpbmdQaWVjZV8gPSAiIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbFN0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nUGllY2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDA0MDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nX3BpZWNlID0gMjQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU3RyaW5nUGllY2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPcHRpb25hbFN0cmluZ1BpZWNlKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxTdHJpbmdQaWVjZV87CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9IHM7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nX3BpZWNlID0gMjQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZ1BpZWNlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0T3B0aW9uYWxTdHJpbmdQaWVjZUJ5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxTdHJpbmdQaWVjZV87CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIG9wdGlvbmFsU3RyaW5nUGllY2VfID0gYjsKICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZ19waWVjZSA9IDI0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsU3RyaW5nUGllY2UgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFN0cmluZ1BpZWNlKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb3B0aW9uYWxTdHJpbmdQaWVjZV8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDA0MDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmdfcGllY2UgPSAyNCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbFN0cmluZ1BpZWNlKCkgewogICAgICAgIG9wdGlvbmFsU3RyaW5nUGllY2VfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0T3B0aW9uYWxTdHJpbmdQaWVjZSgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwNDAwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZ19waWVjZSA9IDI0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZ1BpZWNlIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTdHJpbmdQaWVjZUJ5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbFN0cmluZ1BpZWNlXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDQwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLmxhbmcuT2JqZWN0IG9wdGlvbmFsQ29yZF8gPSAiIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9jb3JkID0gMjUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbENvcmQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDA4MDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxDb3JkLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T3B0aW9uYWxDb3JkKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxDb3JkXzsKICAgICAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0KICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICAgIG9wdGlvbmFsQ29yZF8gPSBzOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX2NvcmQgPSAyNSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbENvcmQuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXRPcHRpb25hbENvcmRCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IG9wdGlvbmFsQ29yZF87CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIG9wdGlvbmFsQ29yZF8gPSBiOwogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbENvcmQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbENvcmQoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbENvcmRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwODAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfY29yZCA9IDI1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbENvcmQoKSB7CiAgICAgICAgb3B0aW9uYWxDb3JkXyA9IGdldERlZmF1bHRJbnN0YW5jZSgpLmdldE9wdGlvbmFsQ29yZCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwODAwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX2NvcmQgPSAyNSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIG9wdGlvbmFsQ29yZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsQ29yZEJ5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbENvcmRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwODAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4gb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDEwMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKCkgewogICAgICAgIGlmIChvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMTAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMTAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAxMDAwMDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAxMDAwMDAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDEwMDAwMDApOwogICAgICAgIG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBEZWZpbmVkIGluIHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8KICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUgb3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNzYWdlID0gMjY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDEwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogRGVmaW5lZCBpbiB1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlIG9wdGlvbmFsX3B1YmxpY19pbXBvcnRfbWVzc2FnZSA9IDI2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxwcmU+CiAgICAgICAqIERlZmluZWQgaW4gdW5pdHRlc3RfaW1wb3J0X3B1YmxpYy5wcm90bwogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSBvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2UgPSAyNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydFB1YmxpY0xpdGUuUHVibGljSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsUHVibGljSW1wb3J0TWVzc2FnZSgpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxMYXp5TWVzc2FnZV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbExhenlNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsTGF6eU1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDIwMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbExhenlNZXNzYWdlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRPcHRpb25hbExhenlNZXNzYWdlKCkgewogICAgICAgIGlmIChvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsTGF6eU1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbExhenlNZXNzYWdlXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxMYXp5TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZV8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDIwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfbGF6eV9tZXNzYWdlID0gMjcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbExhenlNZXNzYWdlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMjAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxMYXp5TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAyMDAwMDAwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlXyAhPSBudWxsICYmCiAgICAgICAgICAgIG9wdGlvbmFsTGF6eU1lc3NhZ2VfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRPcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdGlvbmFsTGF6eU1lc3NhZ2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMjAwMDAwMDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxMYXp5TWVzc2FnZSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMjAwMDAwMCk7CiAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZV8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMjAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF9sYXp5X21lc3NhZ2UgPSAyNyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T3B0aW9uYWxMYXp5TWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxMYXp5TWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxMYXp5TWVzc2FnZV8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxMYXp5TWVzc2FnZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX2xhenlfbWVzc2FnZSA9IDI3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbExhenlNZXNzYWdlKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvcHRpb25hbExhenlNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbExhenlNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF91bnZlcmlmaWVkX2xhenlfbWVzc2FnZSA9IDI4IFt1bnZlcmlmaWVkX2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDQwMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlKCkgewogICAgICAgIGlmIChvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvcHRpb25hbF91bnZlcmlmaWVkX2xhenlfbWVzc2FnZSA9IDI4IFt1bnZlcmlmaWVkX2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDQwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZV8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDA0MDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDQwMDAwMDApICE9IDApICYmCiAgICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyAhPSBudWxsICYmCiAgICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZV8gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDA0MDAwMDAwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDQwMDAwMDApOwogICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDQwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9wdGlvbmFsX3VudmVyaWZpZWRfbGF6eV9tZXNzYWdlID0gMjggW3VudmVyaWZpZWRfbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxVbnZlcmlmaWVkTGF6eU1lc3NhZ2VfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb3B0aW9uYWxfdW52ZXJpZmllZF9sYXp5X21lc3NhZ2UgPSAyOCBbdW52ZXJpZmllZF9sYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsVW52ZXJpZmllZExhenlNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+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+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUxpc3QoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VfKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VDb3VudCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uc2l6ZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8uZ2V0Q291bnQoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkTmVzdGVkTWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWROZXN0ZWRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uc2V0KGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8uYWRkKHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZE5lc3RlZE1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5hZGQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWROZXN0ZWRNZXNzYWdlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5hZGQoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTmVzdGVkTWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWROZXN0ZWRNZXNzYWdlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IHZhbHVlcykgewogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8pOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKHZhbHVlcyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZE5lc3RlZE1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAwMDgwMCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVSZXBlYXRlZE5lc3RlZE1lc3NhZ2UoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZU9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gCiAgICAgICAgICAgZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZE5lc3RlZE1lc3NhZ2VfKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UgPSA0ODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYWRkUmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZSA9IDQ4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBhZGRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX25lc3RlZF9tZXNzYWdlID0gNDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWROZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRSZXBlYXRlZE5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICByZXBlYXRlZE5lc3RlZE1lc3NhZ2VfLAogICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMV8gJiAweDAwMDAwODAwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIHJlcGVhdGVkTmVzdGVkTWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9CiAgICAgICAgamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoISgoYml0RmllbGQxXyAmIDB4MDAwMDEwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IG5ldyBqYXZhLnV0aWwuQXJyYXlMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4ocmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8pOwogICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAxMDAwOwogICAgICAgICB9CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl87CgogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlTGlzdCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZUxpc3QoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlQ291bnQoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uc2l6ZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5nZXQoaW5kZXgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5hZGQodmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmFkZChpbmRleCwgdmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfLmFkZChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKHZhbHVlcyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDEwMDApOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVSZXBlYXRlZEZvcmVpZ25NZXNzYWdlKGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZV8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyIGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcihpbmRleCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VfKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlID0gNDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyIGFkZFJlcGVhdGVkRm9yZWlnbk1lc3NhZ2VCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSByZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UgPSA0OTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIgYWRkUmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZSA9IDQ5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlcj4gCiAgICAgICAgICAgZ2V0UmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJMaXN0KCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRSZXBlYXRlZEZvcmVpZ25NZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChyZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduTWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXywKICAgICAgICAgICAgICAgICAgKChiaXRGaWVsZDFfICYgMHgwMDAwMTAwMCkgIT0gMCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGU+IHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkSW1wb3J0TWVzc2FnZUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoISgoYml0RmllbGQxXyAmIDB4MDAwMDIwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGU+KHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8pOwogICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDAyMDAwOwogICAgICAgICB9CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyPiByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXzsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlPiBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlTGlzdCgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlQ291bnQoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLnNpemUoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uZ2V0KGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW1wb3J0TWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW1wb3J0TWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uYWRkKHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLmFkZChpbmRleCwgdmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydE1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEltcG9ydE1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRJbXBvcnRNZXNzYWdlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW1wb3J0TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkSW1wb3J0TWVzc2FnZSgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVJlcGVhdGVkSW1wb3J0TWVzc2FnZShpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2VMaXRlIHJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlID0gNTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZU9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGUgcmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2UgPSA1MDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8pOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyIGFkZFJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkSW1wb3J0TWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyIGFkZFJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGl0ZSByZXBlYXRlZF9pbXBvcnRfbWVzc2FnZSA9IDUwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRJbXBvcnRNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRSZXBlYXRlZEltcG9ydE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRNZXNzYWdlTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VfLAogICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMV8gJiAweDAwMDAyMDAwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIHJlcGVhdGVkSW1wb3J0TWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IHJlcGVhdGVkTmVzdGVkRW51bV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkTmVzdGVkRW51bUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoISgoYml0RmllbGQxXyAmIDB4MDAwMDQwMDApICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8amF2YS5sYW5nLkludGVnZXI+KHJlcGVhdGVkTmVzdGVkRW51bV8pOwogICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDA0MDAwOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWROZXN0ZWRFbnVtLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bT4gZ2V0UmVwZWF0ZWROZXN0ZWRFbnVtTGlzdCgpIHsKICAgICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXI8CiAgICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+KHJlcGVhdGVkTmVzdGVkRW51bV8sIHJlcGVhdGVkTmVzdGVkRW51bV9jb252ZXJ0ZXJfKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWROZXN0ZWRFbnVtLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZE5lc3RlZEVudW1Db3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWROZXN0ZWRFbnVtXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gcmVwZWF0ZWRfbmVzdGVkX2VudW0gPSA1MTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZE5lc3RlZEVudW0gYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBnZXRSZXBlYXRlZE5lc3RlZEVudW0oaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkTmVzdGVkRW51bV9jb252ZXJ0ZXJfLmNvbnZlcnQocmVwZWF0ZWROZXN0ZWRFbnVtXy5nZXQoaW5kZXgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkTmVzdGVkRW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkTmVzdGVkRW51bSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBlbnN1cmVSZXBlYXRlZE5lc3RlZEVudW1Jc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fLnNldChpbmRleCwgdmFsdWUuZ2V0TnVtYmVyKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkTmVzdGVkRW51bSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTmVzdGVkRW51bShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkRW51bUlzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkTmVzdGVkRW51bV8uYWRkKHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXBlYXRlZF9uZXN0ZWRfZW51bSA9IDUxOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWROZXN0ZWRFbnVtIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWROZXN0ZWRFbnVtKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkTmVzdGVkRW51bUlzTXV0YWJsZSgpOwogICAgICAgIGZvciAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHZhbHVlIDogdmFsdWVzKSB7CiAgICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fLmFkZCh2YWx1ZS5nZXROdW1iZXIoKSk7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIHJlcGVhdGVkX25lc3RlZF9lbnVtID0gNTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkTmVzdGVkRW51bSgpIHsKICAgICAgICByZXBlYXRlZE5lc3RlZEVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDA0MDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gcmVwZWF0ZWRGb3JlaWduRW51bV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkRm9yZWlnbkVudW1Jc011dGFibGUoKSB7CiAgICAgICAgaWYgKCEoKGJpdEZpZWxkMV8gJiAweDAwMDA4MDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8gPSBuZXcgamF2YS51dGlsLkFycmF5TGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4ocmVwZWF0ZWRGb3JlaWduRW51bV8pOwogICAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDA4MDAwOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRm9yZWlnbkVudW0uCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPiBnZXRSZXBlYXRlZEZvcmVpZ25FbnVtTGlzdCgpIHsKICAgICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXI8CiAgICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+KHJlcGVhdGVkRm9yZWlnbkVudW1fLCByZXBlYXRlZEZvcmVpZ25FbnVtX2NvbnZlcnRlcl8pOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHJlcGVhdGVkX2ZvcmVpZ25fZW51bSA9IDUyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGb3JlaWduRW51bS4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGb3JlaWduRW51bUNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEZvcmVpZ25FbnVtXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9lbnVtID0gNTI7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGb3JlaWduRW51bSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldFJlcGVhdGVkRm9yZWlnbkVudW0oaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkRm9yZWlnbkVudW1fY29udmVydGVyXy5jb252ZXJ0KHJlcGVhdGVkRm9yZWlnbkVudW1fLmdldChpbmRleCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHJlcGVhdGVkX2ZvcmVpZ25fZW51bSA9IDUyOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkRm9yZWlnbkVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZvcmVpZ25FbnVtKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbkVudW1Jc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEZvcmVpZ25FbnVtXy5zZXQoaW5kZXgsIHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRGb3JlaWduRW51bSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRm9yZWlnbkVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBlbnN1cmVSZXBlYXRlZEZvcmVpZ25FbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8uYWRkKHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSByZXBlYXRlZF9mb3JlaWduX2VudW0gPSA1Mjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkRm9yZWlnbkVudW0gdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEZvcmVpZ25FbnVtKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkRm9yZWlnbkVudW1Jc011dGFibGUoKTsKICAgICAgICBmb3IgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSB2YWx1ZSA6IHZhbHVlcykgewogICAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8uYWRkKHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcmVwZWF0ZWRfZm9yZWlnbl9lbnVtID0gNTI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkRm9yZWlnbkVudW0oKSB7CiAgICAgICAgcmVwZWF0ZWRGb3JlaWduRW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwMDgwMDApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiByZXBlYXRlZEltcG9ydEVudW1fID0KICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEltcG9ydEVudW1Jc011dGFibGUoKSB7CiAgICAgICAgaWYgKCEoKGJpdEZpZWxkMV8gJiAweDAwMDEwMDAwKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRJbXBvcnRFbnVtXyA9IG5ldyBqYXZhLnV0aWwuQXJyYXlMaXN0PGphdmEubGFuZy5JbnRlZ2VyPihyZXBlYXRlZEltcG9ydEVudW1fKTsKICAgICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAxMDAwMDsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW1wb3J0RW51bS4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4gZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtTGlzdCgpIHsKICAgICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXI8CiAgICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4ocmVwZWF0ZWRJbXBvcnRFbnVtXywgcmVwZWF0ZWRJbXBvcnRFbnVtX2NvbnZlcnRlcl8pOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEltcG9ydEVudW0uCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW1wb3J0RW51bUNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydEVudW1fLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSByZXBlYXRlZF9pbXBvcnRfZW51bSA9IDUzOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW1wb3J0RW51bSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0UmVwZWF0ZWRJbXBvcnRFbnVtKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEltcG9ydEVudW1fY29udmVydGVyXy5jb252ZXJ0KHJlcGVhdGVkSW1wb3J0RW51bV8uZ2V0KGluZGV4KSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgcmVwZWF0ZWRfaW1wb3J0X2VudW0gPSA1Mzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEltcG9ydEVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEltcG9ydEVudW0oCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydEVudW1Jc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEltcG9ydEVudW1fLnNldChpbmRleCwgdmFsdWUuZ2V0TnVtYmVyKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkSW1wb3J0RW51bSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkSW1wb3J0RW51bShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbXBvcnRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRJbXBvcnRFbnVtXy5hZGQodmFsdWUuZ2V0TnVtYmVyKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEltcG9ydEVudW0gdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEltcG9ydEVudW0oCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZEltcG9ydEVudW1Jc011dGFibGUoKTsKICAgICAgICBmb3IgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlIHZhbHVlIDogdmFsdWVzKSB7CiAgICAgICAgICByZXBlYXRlZEltcG9ydEVudW1fLmFkZCh2YWx1ZS5nZXROdW1iZXIoKSk7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIHJlcGVhdGVkX2ltcG9ydF9lbnVtID0gNTM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkSW1wb3J0RW51bSgpIHsKICAgICAgICByZXBlYXRlZEltcG9ydEVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDEwMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QgcmVwZWF0ZWRTdHJpbmdQaWVjZV8gPQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRTdHJpbmdQaWVjZUlzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkU3RyaW5nUGllY2VfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZFN0cmluZ1BpZWNlXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QocmVwZWF0ZWRTdHJpbmdQaWVjZV8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMjAwMDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRTdHJpbmdQaWVjZS4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlByb3RvY29sU3RyaW5nTGlzdAogICAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUxpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRTdHJpbmdQaWVjZV8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZFN0cmluZ1BpZWNlXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZFN0cmluZ1BpZWNlLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkU3RyaW5nUGllY2VfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRTdHJpbmdQaWVjZSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRSZXBlYXRlZFN0cmluZ1BpZWNlKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZFN0cmluZ1BpZWNlXy5nZXQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHZhbHVlIHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkU3RyaW5nUGllY2UgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0UmVwZWF0ZWRTdHJpbmdQaWVjZUJ5dGVzKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZFN0cmluZ1BpZWNlXy5nZXRCeXRlU3RyaW5nKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRTdHJpbmdQaWVjZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkU3RyaW5nUGllY2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nUGllY2VJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFN0cmluZ1BpZWNlXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRTdHJpbmdQaWVjZSgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nUGllY2VJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFN0cmluZ1BpZWNlXy5hZGQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAyMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX3N0cmluZ19waWVjZSA9IDU0IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZFN0cmluZ1BpZWNlIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRTdHJpbmdQaWVjZSgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTxqYXZhLmxhbmcuU3RyaW5nPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZFN0cmluZ1BpZWNlSXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkU3RyaW5nUGllY2VfKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9zdHJpbmdfcGllY2UgPSA1NCBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZFN0cmluZ1BpZWNlKCkgewogICAgICAgIHJlcGVhdGVkU3RyaW5nUGllY2VfID0KICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdC5lbXB0eUxpc3QoKTsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDAyMDAwMCk7OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfc3RyaW5nX3BpZWNlID0gNTQgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgb2YgdGhlIHJlcGVhdGVkU3RyaW5nUGllY2UgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZFN0cmluZ1BpZWNlQnl0ZXMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkU3RyaW5nUGllY2VJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZFN0cmluZ1BpZWNlXy5hZGQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDAyMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QgcmVwZWF0ZWRDb3JkXyA9CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkxhenlTdHJpbmdBcnJheUxpc3QuZW1wdHlMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZENvcmRJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZENvcmRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZENvcmRfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTGF6eVN0cmluZ0FycmF5TGlzdChyZXBlYXRlZENvcmRfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwMDQwMDAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRDb3JkLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xTdHJpbmdMaXN0CiAgICAgICAgICBnZXRSZXBlYXRlZENvcmRMaXN0KCkgewogICAgICAgIHJlcGVhdGVkQ29yZF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZENvcmRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRDb3JkLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZENvcmRDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRDb3JkXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRDb3JkIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldFJlcGVhdGVkQ29yZChpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRDb3JkXy5nZXQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdmFsdWUgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBvZiB0aGUgcmVwZWF0ZWRDb3JkIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldFJlcGVhdGVkQ29yZEJ5dGVzKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZENvcmRfLmdldEJ5dGVTdHJpbmcoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzdHJpbmcgcmVwZWF0ZWRfY29yZCA9IDU1IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkQ29yZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkQ29yZCgKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRDb3JkSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRDb3JkXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwNDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkQ29yZCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkQ29yZCgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGVuc3VyZVJlcGVhdGVkQ29yZElzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkQ29yZF8uYWRkKHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwNDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZENvcmQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZENvcmQoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8amF2YS5sYW5nLlN0cmluZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRDb3JkSXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkQ29yZF8pOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDA0MDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc3RyaW5nIHJlcGVhdGVkX2NvcmQgPSA1NSBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRDb3JkKCkgewogICAgICAgIHJlcGVhdGVkQ29yZF8gPQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5MYXp5U3RyaW5nQXJyYXlMaXN0LmVtcHR5TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMDQwMDAwKTs7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHN0cmluZyByZXBlYXRlZF9jb3JkID0gNTUgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIG9mIHRoZSByZXBlYXRlZENvcmQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZENvcmRCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZW5zdXJlUmVwZWF0ZWRDb3JkSXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRDb3JkXy5hZGQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDA0MDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0KICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZExhenlNZXNzYWdlSXNNdXRhYmxlKCkgewogICAgICAgIGlmICghKChiaXRGaWVsZDFfICYgMHgwMDA4MDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPihyZXBlYXRlZExhenlNZXNzYWdlXyk7CiAgICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAwODAwMDA7CiAgICAgICAgIH0KICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXzsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUxpc3QoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRMYXp5TWVzc2FnZV8pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZExhenlNZXNzYWdlQ291bnQoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZV8uc2l6ZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBnZXRSZXBlYXRlZExhenlNZXNzYWdlKGludCBpbmRleCkgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmdldChpbmRleCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZShpbmRleCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRMYXp5TWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTGF6eU1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRMYXp5TWVzc2FnZSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZExhenlNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTGF6eU1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTGF6eU1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmFkZCh2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTGF6eU1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZExhenlNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXy5hZGQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTGF6eU1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkTGF6eU1lc3NhZ2VJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkTGF6eU1lc3NhZ2UoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRMYXp5TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZV8uYWRkKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZExhenlNZXNzYWdlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IHZhbHVlcykgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRMYXp5TWVzc2FnZUlzTXV0YWJsZSgpOwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRMYXp5TWVzc2FnZV8pOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyh2YWx1ZXMpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRMYXp5TWVzc2FnZSgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAwODAwMDApOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVJlcGVhdGVkTGF6eU1lc3NhZ2UoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZExhenlNZXNzYWdlSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5yZW1vdmUoaW5kZXgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBnZXRSZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZExhenlNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZExhenlNZXNzYWdlXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcihpbmRleCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgICAgIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRMYXp5TWVzc2FnZV8pOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSByZXBlYXRlZF9sYXp5X21lc3NhZ2UgPSA1NyBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBhZGRSZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgcmVwZWF0ZWRfbGF6eV9tZXNzYWdlID0gNTcgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYWRkUmVwZWF0ZWRMYXp5TWVzc2FnZUJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ2V0UmVwZWF0ZWRMYXp5TWVzc2FnZUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgIGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHJlcGVhdGVkX2xhenlfbWVzc2FnZSA9IDU3IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyPiAKICAgICAgICAgICBnZXRSZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlckxpc3QoKSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyTGlzdCgpOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldFJlcGVhdGVkTGF6eU1lc3NhZ2VGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXBlYXRlZExhenlNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfLAogICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMV8gJiAweDAwMDgwMDAwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkTGF6eU1lc3NhZ2VCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZGVmYXVsdEludDMyXyA9IDQxOwogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogU2luZ3VsYXIgd2l0aCBkZWZhdWx0cwogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVmYXVsdF9pbnQzMiA9IDYxIFtkZWZhdWx0ID0gNDFdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0SW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0SW50MzIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDAxMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBTaW5ndWxhciB3aXRoIGRlZmF1bHRzCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWZhdWx0X2ludDMyID0gNjEgW2RlZmF1bHQgPSA0MV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0SW50MzIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RGVmYXVsdEludDMyKCkgewogICAgICAgIHJldHVybiBkZWZhdWx0SW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBTaW5ndWxhciB3aXRoIGRlZmF1bHRzCiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWZhdWx0X2ludDMyID0gNjEgW2RlZmF1bHQgPSA0MV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRJbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRJbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdEludDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgwMDEwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogU2luZ3VsYXIgd2l0aCBkZWZhdWx0cwogICAgICAgKiA8L3ByZT4KICAgICAgICoKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVmYXVsdF9pbnQzMiA9IDYxIFtkZWZhdWx0ID0gNDFdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0SW50MzIoKSB7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4MDAxMDAwMDApOwogICAgICAgIGRlZmF1bHRJbnQzMl8gPSA0MTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBsb25nIGRlZmF1bHRJbnQ2NF8gPSA0Mkw7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBkZWZhdWx0X2ludDY0ID0gNjIgW2RlZmF1bHQgPSA0Ml07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRJbnQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRJbnQ2NCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMDIwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGRlZmF1bHRfaW50NjQgPSA2MiBbZGVmYXVsdCA9IDQyXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRJbnQ2NC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0RGVmYXVsdEludDY0KCkgewogICAgICAgIHJldHVybiBkZWZhdWx0SW50NjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQ2NCBkZWZhdWx0X2ludDY0ID0gNjIgW2RlZmF1bHQgPSA0Ml07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRJbnQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRJbnQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIGRlZmF1bHRJbnQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDAyMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDY0IGRlZmF1bHRfaW50NjQgPSA2MiBbZGVmYXVsdCA9IDQyXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdEludDY0KCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwMjAwMDAwKTsKICAgICAgICBkZWZhdWx0SW50NjRfID0gNDJMOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBkZWZhdWx0VWludDMyXyA9IDQzOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIGRlZmF1bHRfdWludDMyID0gNjMgW2RlZmF1bHQgPSA0M107PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0VWludDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwNDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDMyIGRlZmF1bHRfdWludDMyID0gNjMgW2RlZmF1bHQgPSA0M107PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0VWludDMyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldERlZmF1bHRVaW50MzIoKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRVaW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgZGVmYXVsdF91aW50MzIgPSA2MyBbZGVmYXVsdCA9IDQzXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdFVpbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRVaW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIGRlZmF1bHRVaW50MzJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAwNDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCB1aW50MzIgZGVmYXVsdF91aW50MzIgPSA2MyBbZGVmYXVsdCA9IDQzXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdFVpbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMDQwMDAwMCk7CiAgICAgICAgZGVmYXVsdFVpbnQzMl8gPSA0MzsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBsb25nIGRlZmF1bHRVaW50NjRfID0gNDRMOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IGRlZmF1bHRfdWludDY0ID0gNjQgW2RlZmF1bHQgPSA0NF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRVaW50NjQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0VWludDY0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAwODAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IGRlZmF1bHRfdWludDY0ID0gNjQgW2RlZmF1bHQgPSA0NF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0VWludDY0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXREZWZhdWx0VWludDY0KCkgewogICAgICAgIHJldHVybiBkZWZhdWx0VWludDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgdWludDY0IGRlZmF1bHRfdWludDY0ID0gNjQgW2RlZmF1bHQgPSA0NF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRVaW50NjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0VWludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdFVpbnQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDA4MDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHVpbnQ2NCBkZWZhdWx0X3VpbnQ2NCA9IDY0IFtkZWZhdWx0ID0gNDRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0VWludDY0KCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDAwODAwMDAwKTsKICAgICAgICBkZWZhdWx0VWludDY0XyA9IDQ0TDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZGVmYXVsdFNpbnQzMl8gPSAtNDU7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50MzIgZGVmYXVsdF9zaW50MzIgPSA2NSBbZGVmYXVsdCA9IC00NV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTaW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0U2ludDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDAxMDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIGRlZmF1bHRfc2ludDMyID0gNjUgW2RlZmF1bHQgPSAtNDVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdFNpbnQzMi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXREZWZhdWx0U2ludDMyKCkgewogICAgICAgIHJldHVybiBkZWZhdWx0U2ludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ludDMyIGRlZmF1bHRfc2ludDMyID0gNjUgW2RlZmF1bHQgPSAtNDVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0U2ludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdFNpbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdFNpbnQzMl8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDEwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQzMiBkZWZhdWx0X3NpbnQzMiA9IDY1IFtkZWZhdWx0ID0gLTQ1XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdFNpbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMTAwMDAwMCk7CiAgICAgICAgZGVmYXVsdFNpbnQzMl8gPSAtNDU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgbG9uZyBkZWZhdWx0U2ludDY0XyA9IDQ2TDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBkZWZhdWx0X3NpbnQ2NCA9IDY2IFtkZWZhdWx0ID0gNDZdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U2ludDY0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdFNpbnQ2NCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwMjAwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBkZWZhdWx0X3NpbnQ2NCA9IDY2IFtkZWZhdWx0ID0gNDZdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdFNpbnQ2NC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0RGVmYXVsdFNpbnQ2NCgpIHsKICAgICAgICByZXR1cm4gZGVmYXVsdFNpbnQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNpbnQ2NCBkZWZhdWx0X3NpbnQ2NCA9IDY2IFtkZWZhdWx0ID0gNDZdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0U2ludDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdFNpbnQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIGRlZmF1bHRTaW50NjRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQxXyB8PSAweDAyMDAwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzaW50NjQgZGVmYXVsdF9zaW50NjQgPSA2NiBbZGVmYXVsdCA9IDQ2XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdFNpbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHgwMjAwMDAwMCk7CiAgICAgICAgZGVmYXVsdFNpbnQ2NF8gPSA0Nkw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGRlZmF1bHRGaXhlZDMyXyA9IDQ3OwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZml4ZWQzMiBkZWZhdWx0X2ZpeGVkMzIgPSA2NyBbZGVmYXVsdCA9IDQ3XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Rml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgwNDAwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkMzIgZGVmYXVsdF9maXhlZDMyID0gNjcgW2RlZmF1bHQgPSA0N107PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0Rml4ZWQzMi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXREZWZhdWx0Rml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gZGVmYXVsdEZpeGVkMzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDMyIGRlZmF1bHRfZml4ZWQzMiA9IDY3IFtkZWZhdWx0ID0gNDddOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0Rml4ZWQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRGaXhlZDMyKGludCB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0Rml4ZWQzMl8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDQwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkMzIgZGVmYXVsdF9maXhlZDMyID0gNjcgW2RlZmF1bHQgPSA0N107PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRGaXhlZDMyKCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDA0MDAwMDAwKTsKICAgICAgICBkZWZhdWx0Rml4ZWQzMl8gPSA0NzsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBsb25nIGRlZmF1bHRGaXhlZDY0XyA9IDQ4TDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgZGVmYXVsdF9maXhlZDY0ID0gNjggW2RlZmF1bHQgPSA0OF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRGaXhlZDY0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEZpeGVkNjQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQxXyAmIDB4MDgwMDAwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmaXhlZDY0IGRlZmF1bHRfZml4ZWQ2NCA9IDY4IFtkZWZhdWx0ID0gNDhdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdEZpeGVkNjQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldERlZmF1bHRGaXhlZDY0KCkgewogICAgICAgIHJldHVybiBkZWZhdWx0Rml4ZWQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgZGVmYXVsdF9maXhlZDY0ID0gNjggW2RlZmF1bHQgPSA0OF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRGaXhlZDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdEZpeGVkNjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0Rml4ZWQ2NF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MDgwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZpeGVkNjQgZGVmYXVsdF9maXhlZDY0ID0gNjggW2RlZmF1bHQgPSA0OF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRGaXhlZDY0KCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDA4MDAwMDAwKTsKICAgICAgICBkZWZhdWx0Rml4ZWQ2NF8gPSA0OEw7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGRlZmF1bHRTZml4ZWQzMl8gPSA0OTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIGRlZmF1bHRfc2ZpeGVkMzIgPSA2OSBbZGVmYXVsdCA9IDQ5XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFNmaXhlZDMyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdFNmaXhlZDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDEwMDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgZGVmYXVsdF9zZml4ZWQzMiA9IDY5IFtkZWZhdWx0ID0gNDldOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdFNmaXhlZDMyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldERlZmF1bHRTZml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gZGVmYXVsdFNmaXhlZDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkMzIgZGVmYXVsdF9zZml4ZWQzMiA9IDY5IFtkZWZhdWx0ID0gNDldOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0U2ZpeGVkMzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0U2ZpeGVkMzIoaW50IHZhbHVlKSB7CgogICAgICAgIGRlZmF1bHRTZml4ZWQzMl8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDFfIHw9IDB4MTAwMDAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDMyIGRlZmF1bHRfc2ZpeGVkMzIgPSA2OSBbZGVmYXVsdCA9IDQ5XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdFNmaXhlZDMyKCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDEwMDAwMDAwKTsKICAgICAgICBkZWZhdWx0U2ZpeGVkMzJfID0gNDk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgbG9uZyBkZWZhdWx0U2ZpeGVkNjRfID0gLTUwTDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IGRlZmF1bHRfc2ZpeGVkNjQgPSA3MCBbZGVmYXVsdCA9IC01MF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRTZml4ZWQ2NCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTZml4ZWQ2NCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHgyMDAwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHNmaXhlZDY0IGRlZmF1bHRfc2ZpeGVkNjQgPSA3MCBbZGVmYXVsdCA9IC01MF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0U2ZpeGVkNjQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldERlZmF1bHRTZml4ZWQ2NCgpIHsKICAgICAgICByZXR1cm4gZGVmYXVsdFNmaXhlZDY0XzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgZGVmYXVsdF9zZml4ZWQ2NCA9IDcwIFtkZWZhdWx0ID0gLTUwXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdFNmaXhlZDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdFNmaXhlZDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdFNmaXhlZDY0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHgyMDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc2ZpeGVkNjQgZGVmYXVsdF9zZml4ZWQ2NCA9IDcwIFtkZWZhdWx0ID0gLTUwXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdFNmaXhlZDY0KCkgewogICAgICAgIGJpdEZpZWxkMV8gPSAoYml0RmllbGQxXyAmIH4weDIwMDAwMDAwKTsKICAgICAgICBkZWZhdWx0U2ZpeGVkNjRfID0gLTUwTDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBmbG9hdCBkZWZhdWx0RmxvYXRfID0gNTEuNUY7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBmbG9hdCBkZWZhdWx0X2Zsb2F0ID0gNzEgW2RlZmF1bHQgPSA1MS41XTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEZsb2F0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdEZsb2F0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMV8gJiAweDQwMDAwMDAwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgZGVmYXVsdF9mbG9hdCA9IDcxIFtkZWZhdWx0ID0gNTEuNV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWZhdWx0RmxvYXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmbG9hdCBnZXREZWZhdWx0RmxvYXQoKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRGbG9hdF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGZsb2F0IGRlZmF1bHRfZmxvYXQgPSA3MSBbZGVmYXVsdCA9IDUxLjVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0RmxvYXQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0RmxvYXQoZmxvYXQgdmFsdWUpIHsKCiAgICAgICAgZGVmYXVsdEZsb2F0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHg0MDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZmxvYXQgZGVmYXVsdF9mbG9hdCA9IDcxIFtkZWZhdWx0ID0gNTEuNV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRGbG9hdCgpIHsKICAgICAgICBiaXRGaWVsZDFfID0gKGJpdEZpZWxkMV8gJiB+MHg0MDAwMDAwMCk7CiAgICAgICAgZGVmYXVsdEZsb2F0XyA9IDUxLjVGOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGRvdWJsZSBkZWZhdWx0RG91YmxlXyA9IDUyMDAwRDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBkZWZhdWx0X2RvdWJsZSA9IDcyIFtkZWZhdWx0ID0gNTIwMDBdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0RG91YmxlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdERvdWJsZSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDFfICYgMHg4MDAwMDAwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGRvdWJsZSBkZWZhdWx0X2RvdWJsZSA9IDcyIFtkZWZhdWx0ID0gNTIwMDBdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdERvdWJsZS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGRvdWJsZSBnZXREZWZhdWx0RG91YmxlKCkgewogICAgICAgIHJldHVybiBkZWZhdWx0RG91YmxlXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIGRlZmF1bHRfZG91YmxlID0gNzIgW2RlZmF1bHQgPSA1MjAwMF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHREb3VibGUgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0RG91YmxlKGRvdWJsZSB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0RG91YmxlXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMV8gfD0gMHg4MDAwMDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZG91YmxlIGRlZmF1bHRfZG91YmxlID0gNzIgW2RlZmF1bHQgPSA1MjAwMF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHREb3VibGUoKSB7CiAgICAgICAgYml0RmllbGQxXyA9IChiaXRGaWVsZDFfICYgfjB4ODAwMDAwMDApOwogICAgICAgIGRlZmF1bHREb3VibGVfID0gNTIwMDBEOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGJvb2xlYW4gZGVmYXVsdEJvb2xfID0gdHJ1ZTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgZGVmYXVsdF9ib29sID0gNzMgW2RlZmF1bHQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEJvb2wgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Qm9vbCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDJfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgZGVmYXVsdF9ib29sID0gNzMgW2RlZmF1bHQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRCb29sLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBnZXREZWZhdWx0Qm9vbCgpIHsKICAgICAgICByZXR1cm4gZGVmYXVsdEJvb2xfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBib29sIGRlZmF1bHRfYm9vbCA9IDczIFtkZWZhdWx0ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRCb29sIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdEJvb2woYm9vbGVhbiB2YWx1ZSkgewoKICAgICAgICBkZWZhdWx0Qm9vbF8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJvb2wgZGVmYXVsdF9ib29sID0gNzMgW2RlZmF1bHQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdEJvb2woKSB7CiAgICAgICAgYml0RmllbGQyXyA9IChiaXRGaWVsZDJfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGRlZmF1bHRCb29sXyA9IHRydWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBkZWZhdWx0U3RyaW5nXyA9ICJoZWxsbyI7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmcgPSA3NCBbZGVmYXVsdCA9ICJoZWxsbyJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0U3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTdHJpbmcoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQyXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmcgPSA3NCBbZGVmYXVsdCA9ICJoZWxsbyJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdFN0cmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldERlZmF1bHRTdHJpbmcoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0U3RyaW5nXzsKICAgICAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0KICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICAgIGRlZmF1bHRTdHJpbmdfID0gczsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZyA9IDc0IFtkZWZhdWx0ID0gImhlbGxvIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVmYXVsdFN0cmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldERlZmF1bHRTdHJpbmdCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlZmF1bHRTdHJpbmdfOwogICAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBTdHJpbmcpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgICBkZWZhdWx0U3RyaW5nXyA9IGI7CiAgICAgICAgICByZXR1cm4gYjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZyA9IDc0IFtkZWZhdWx0ID0gImhlbGxvIl07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0U3RyaW5nKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZGVmYXVsdFN0cmluZ18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZyA9IDc0IFtkZWZhdWx0ID0gImhlbGxvIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRTdHJpbmcoKSB7CiAgICAgICAgZGVmYXVsdFN0cmluZ18gPSBnZXREZWZhdWx0SW5zdGFuY2UoKS5nZXREZWZhdWx0U3RyaW5nKCk7CiAgICAgICAgYml0RmllbGQyXyA9IChiaXRGaWVsZDJfICYgfjB4MDAwMDAwMDIpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmcgPSA3NCBbZGVmYXVsdCA9ICJoZWxsbyJdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBieXRlcyBmb3IgZGVmYXVsdFN0cmluZyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRTdHJpbmdCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZGVmYXVsdFN0cmluZ18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRlZmF1bHRCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLmJ5dGVzRGVmYXVsdFZhbHVlKCJ3b3JsZCIpOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgZGVmYXVsdF9ieXRlcyA9IDc1IFtkZWZhdWx0ID0gIndvcmxkIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlZmF1bHRCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRCeXRlcygpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDJfICYgMHgwMDAwMDAwNCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIGRlZmF1bHRfYnl0ZXMgPSA3NSBbZGVmYXVsdCA9ICJ3b3JsZCJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZGVmYXVsdEJ5dGVzLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldERlZmF1bHRCeXRlcygpIHsKICAgICAgICByZXR1cm4gZGVmYXVsdEJ5dGVzXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgZGVmYXVsdF9ieXRlcyA9IDc1IFtkZWZhdWx0ID0gIndvcmxkIl07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRCeXRlcyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRCeXRlcyhjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGRlZmF1bHRCeXRlc18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIGRlZmF1bHRfYnl0ZXMgPSA3NSBbZGVmYXVsdCA9ICJ3b3JsZCJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0Qnl0ZXMoKSB7CiAgICAgICAgYml0RmllbGQyXyA9IChiaXRGaWVsZDJfICYgfjB4MDAwMDAwMDQpOwogICAgICAgIGRlZmF1bHRCeXRlc18gPSBnZXREZWZhdWx0SW5zdGFuY2UoKS5nZXREZWZhdWx0Qnl0ZXMoKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZGVmYXVsdE5lc3RlZEVudW1fID0gMjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gZGVmYXVsdF9uZXN0ZWRfZW51bSA9IDgxIFtkZWZhdWx0ID0gQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdE5lc3RlZEVudW0gZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0TmVzdGVkRW51bSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDJfICYgMHgwMDAwMDAwOCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0gZGVmYXVsdF9uZXN0ZWRfZW51bSA9IDgxIFtkZWZhdWx0ID0gQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHROZXN0ZWRFbnVtLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGdldERlZmF1bHROZXN0ZWRFbnVtKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uZm9yTnVtYmVyKGRlZmF1bHROZXN0ZWRFbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLkJBUiA6IHJlc3VsdDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSBkZWZhdWx0X25lc3RlZF9lbnVtID0gODEgW2RlZmF1bHQgPSBCQVJdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0TmVzdGVkRW51bSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHROZXN0ZWRFbnVtKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW51bSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDA4OwogICAgICAgIGRlZmF1bHROZXN0ZWRFbnVtXyA9IHZhbHVlLmdldE51bWJlcigpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIGRlZmF1bHRfbmVzdGVkX2VudW0gPSA4MSBbZGVmYXVsdCA9IEJBUl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHROZXN0ZWRFbnVtKCkgewogICAgICAgIGJpdEZpZWxkMl8gPSAoYml0RmllbGQyXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICBkZWZhdWx0TmVzdGVkRW51bV8gPSAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBkZWZhdWx0Rm9yZWlnbkVudW1fID0gNTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZWZhdWx0Rm9yZWlnbkVudW0gZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0Rm9yZWlnbkVudW0oKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQyXyAmIDB4MDAwMDAwMTApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIGRlZmF1bHRfZm9yZWlnbl9lbnVtID0gODIgW2RlZmF1bHQgPSBGT1JFSUdOX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRGb3JlaWduRW51bS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSBnZXREZWZhdWx0Rm9yZWlnbkVudW0oKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIoZGVmYXVsdEZvcmVpZ25FbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLkZPUkVJR05fTElURV9CQVIgOiByZXN1bHQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgZGVmYXVsdF9mb3JlaWduX2VudW0gPSA4MiBbZGVmYXVsdCA9IEZPUkVJR05fTElURV9CQVJdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBkZWZhdWx0Rm9yZWlnbkVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0Rm9yZWlnbkVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgZGVmYXVsdEZvcmVpZ25FbnVtXyA9IHZhbHVlLmdldE51bWJlcigpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIGRlZmF1bHRfZm9yZWlnbl9lbnVtID0gODIgW2RlZmF1bHQgPSBGT1JFSUdOX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdEZvcmVpZ25FbnVtKCkgewogICAgICAgIGJpdEZpZWxkMl8gPSAoYml0RmllbGQyXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICBkZWZhdWx0Rm9yZWlnbkVudW1fID0gNTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZGVmYXVsdEltcG9ydEVudW1fID0gODsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgZGVmYXVsdF9pbXBvcnRfZW51bSA9IDgzIFtkZWZhdWx0ID0gSU1QT1JUX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdEltcG9ydEVudW0gZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNEZWZhdWx0SW1wb3J0RW51bSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDJfICYgMHgwMDAwMDAyMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bUxpdGUgZGVmYXVsdF9pbXBvcnRfZW51bSA9IDgzIFtkZWZhdWx0ID0gSU1QT1JUX0xJVEVfQkFSXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRJbXBvcnRFbnVtLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgZ2V0RGVmYXVsdEltcG9ydEVudW0oKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuZm9yTnVtYmVyKGRlZmF1bHRJbXBvcnRFbnVtXyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUuSU1QT1JUX0xJVEVfQkFSIDogcmVzdWx0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlIGRlZmF1bHRfaW1wb3J0X2VudW0gPSA4MyBbZGVmYXVsdCA9IElNUE9SVF9MSVRFX0JBUl07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRJbXBvcnRFbnVtIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdEltcG9ydEVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0RW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDAyMDsKICAgICAgICBkZWZhdWx0SW1wb3J0RW51bV8gPSB2YWx1ZS5nZXROdW1iZXIoKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZSBkZWZhdWx0X2ltcG9ydF9lbnVtID0gODMgW2RlZmF1bHQgPSBJTVBPUlRfTElURV9CQVJdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWZhdWx0SW1wb3J0RW51bSgpIHsKICAgICAgICBiaXRGaWVsZDJfID0gKGJpdEZpZWxkMl8gJiB+MHgwMDAwMDAyMCk7CiAgICAgICAgZGVmYXVsdEltcG9ydEVudW1fID0gODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLmxhbmcuT2JqZWN0IGRlZmF1bHRTdHJpbmdQaWVjZV8gPSAiYWJjIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdFN0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0RlZmF1bHRTdHJpbmdQaWVjZSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDJfICYgMHgwMDAwMDA0MCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRTdHJpbmdQaWVjZS4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldERlZmF1bHRTdHJpbmdQaWVjZSgpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlZmF1bHRTdHJpbmdQaWVjZV87CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gczsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBkZWZhdWx0U3RyaW5nUGllY2UuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXREZWZhdWx0U3RyaW5nUGllY2VCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlZmF1bHRTdHJpbmdQaWVjZV87CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSBiOwogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9zdHJpbmdfcGllY2UgPSA4NCBbZGVmYXVsdCA9ICJhYmMiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlZmF1bHRTdHJpbmdQaWVjZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRTdHJpbmdQaWVjZSgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDJfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRGVmYXVsdFN0cmluZ1BpZWNlKCkgewogICAgICAgIGRlZmF1bHRTdHJpbmdQaWVjZV8gPSBnZXREZWZhdWx0SW5zdGFuY2UoKS5nZXREZWZhdWx0U3RyaW5nUGllY2UoKTsKICAgICAgICBiaXRGaWVsZDJfID0gKGJpdEZpZWxkMl8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZWZhdWx0X3N0cmluZ19waWVjZSA9IDg0IFtkZWZhdWx0ID0gImFiYyIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIGRlZmF1bHRTdHJpbmdQaWVjZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldERlZmF1bHRTdHJpbmdQaWVjZUJ5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBkZWZhdWx0U3RyaW5nUGllY2VfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDQwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3QgZGVmYXVsdENvcmRfID0gIjEyMyI7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9jb3JkID0gODUgW2RlZmF1bHQgPSAiMTIzIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVmYXVsdENvcmQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVmYXVsdENvcmQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQyXyAmIDB4MDAwMDAwODApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9jb3JkID0gODUgW2RlZmF1bHQgPSAiMTIzIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGRlZmF1bHRDb3JkLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVmYXVsdENvcmQoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZWZhdWx0Q29yZF87CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICBkZWZhdWx0Q29yZF8gPSBzOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVmYXVsdENvcmQuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXREZWZhdWx0Q29yZEJ5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVmYXVsdENvcmRfOwogICAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBTdHJpbmcpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgICBkZWZhdWx0Q29yZF8gPSBiOwogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9jb3JkID0gODUgW2RlZmF1bHQgPSAiMTIzIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVmYXVsdENvcmQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXREZWZhdWx0Q29yZCgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGRlZmF1bHRDb3JkXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlZmF1bHRfY29yZCA9IDg1IFtkZWZhdWx0ID0gIjEyMyIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckRlZmF1bHRDb3JkKCkgewogICAgICAgIGRlZmF1bHRDb3JkXyA9IGdldERlZmF1bHRJbnN0YW5jZSgpLmdldERlZmF1bHRDb3JkKCk7CiAgICAgICAgYml0RmllbGQyXyA9IChiaXRGaWVsZDJfICYgfjB4MDAwMDAwODApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVmYXVsdF9jb3JkID0gODUgW2RlZmF1bHQgPSAiMTIzIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIGRlZmF1bHRDb3JkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVmYXVsdENvcmRCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgZGVmYXVsdENvcmRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQyXyB8PSAweDAwMDAwMDgwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+dWludDMyIG9uZW9mX3VpbnQzMiA9IDExMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZVaW50MzIoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxMTE7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSAxMTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlVpbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0T25lb2ZVaW50MzIoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTEpIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLkludGVnZXIpIG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICByZXR1cm4gMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+dWludDMyIG9uZW9mX3VpbnQzMiA9IDExMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZVaW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlVpbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTExOwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSAxMTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mVWludDMyKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTExKSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZOZXN0ZWRNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZOZXN0ZWRNZXNzYWdlKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTEyOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX25lc3RlZF9tZXNzYWdlID0gMTEyOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZOZXN0ZWRNZXNzYWdlLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIGdldE9uZW9mTmVzdGVkTWVzc2FnZSgpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIpIHsKICAgICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UpIG9uZW9mRmllbGRfOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIpIHsKICAgICAgICAgICAgcmV0dXJuIG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX25lc3RlZF9tZXNzYWdlID0gMTEyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mTmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTI7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZOZXN0ZWRNZXNzYWdlKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9uZW9mRmllbGRfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZU9uZW9mTmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIgJiYKICAgICAgICAgICAgICBvbmVvZkZpZWxkXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UubmV3QnVpbGRlcigoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXykKICAgICAgICAgICAgICAgIC5tZXJnZUZyb20odmFsdWUpLmJ1aWxkUGFydGlhbCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMikgewogICAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mTmVzdGVkTWVzc2FnZSgpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTIpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbmVzdGVkX21lc3NhZ2UgPSAxMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyIGdldE9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIGdldE9uZW9mTmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXIgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICAgIGlmICgob25lb2ZGaWVsZENhc2VfID09IDExMikgJiYgKG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpKSB7CiAgICAgICAgICByZXR1cm4gb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExMikgewogICAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF87CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9uZXN0ZWRfbWVzc2FnZSA9IDExMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvbmVvZk5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoIShvbmVvZkZpZWxkQ2FzZV8gPT0gMTEyKSkgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF8sCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gb25lb2ZOZXN0ZWRNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZTdHJpbmcuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE9uZW9mU3RyaW5nKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gIiI7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTMpIHsKICAgICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0KICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBzOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXRPbmVvZlN0cmluZ0J5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gIiI7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTMpIHsKICAgICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICBpZiAocmVmIGluc3RhbmNlb2YgU3RyaW5nKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTMpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBiOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvbmVvZlN0cmluZyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mU3RyaW5nKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTEzOwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAxMTM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mU3RyaW5nKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTEzKSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMTEzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN0cmluZ0J5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTM7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gMTE0OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mQnl0ZXMoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxMTQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gMTE0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlcy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlcygpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNCkgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDExNDs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZCeXRlcyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mQnl0ZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTQ7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSAxMTQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mQnl0ZXMoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTQpIHsKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlcj4gb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9sYXp5X25lc3RlZF9tZXNzYWdlID0gMTE1IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX2xhenlfbmVzdGVkX21lc3NhZ2UgPSAxMTUgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZSgpIHsKICAgICAgICBpZiAob25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXzsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgICAgIHJldHVybiBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTU7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9uZW9mRmllbGRfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTU7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT25lb2ZMYXp5TmVzdGVkTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1ICYmCiAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLm5ld0J1aWxkZXIoKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF8pCiAgICAgICAgICAgICAgICAubWVyZ2VGcm9tKHZhbHVlKS5idWlsZFBhcnRpYWwoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUpIHsKICAgICAgICAgICAgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExNTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSBvbmVvZl9sYXp5X25lc3RlZF9tZXNzYWdlID0gMTE1IFtsYXp5ID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkxhenlOZXN0ZWRNZXNzYWdlKCkgewogICAgICAgIGlmIChvbmVvZkxhenlOZXN0ZWRNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX2xhenlfbmVzdGVkX21lc3NhZ2UgPSAxMTUgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLkJ1aWxkZXIgZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIGdldE9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2Ugb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZSA9IDExNSBbbGF6eSA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZU9yQnVpbGRlciBnZXRPbmVvZkxhenlOZXN0ZWRNZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICAgIGlmICgob25lb2ZGaWVsZENhc2VfID09IDExNSkgJiYgKG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSkgewogICAgICAgICAgcmV0dXJuIG9uZW9mTGF6eU5lc3RlZE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE1KSB7CiAgICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlKSBvbmVvZkZpZWxkXzsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlIG9uZW9mX2xhenlfbmVzdGVkX21lc3NhZ2UgPSAxMTUgW2xhenkgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T25lb2ZMYXp5TmVzdGVkTWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghKG9uZW9mRmllbGRDYXNlXyA9PSAxMTUpKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZSkgb25lb2ZGaWVsZF8sCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExNTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gb25lb2ZMYXp5TmVzdGVkTWVzc2FnZUJ1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTJPckJ1aWxkZXI+IG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG9uZW9mX25lc3RlZF9tZXNzYWdlMiA9IDExNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZOZXN0ZWRNZXNzYWdlMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mTmVzdGVkTWVzc2FnZTIoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAxMTc7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG9uZW9mX25lc3RlZF9tZXNzYWdlMiA9IDExNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mTmVzdGVkTWVzc2FnZTIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIGdldE9uZW9mTmVzdGVkTWVzc2FnZTIoKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNykgewogICAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpIG9uZW9mRmllbGRfOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSB7CiAgICAgICAgICAgIHJldHVybiBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZOZXN0ZWRNZXNzYWdlMihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlMkJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTc7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG9uZW9mX25lc3RlZF9tZXNzYWdlMiA9IDExNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZk5lc3RlZE1lc3NhZ2UyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDExNzsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIgb25lb2ZfbmVzdGVkX21lc3NhZ2UyID0gMTE3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT25lb2ZOZXN0ZWRNZXNzYWdlMihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIHZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNyAmJgogICAgICAgICAgICAgIG9uZW9mRmllbGRfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLm5ld0J1aWxkZXIoKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIpIG9uZW9mRmllbGRfKQogICAgICAgICAgICAgICAgLm1lcmdlRnJvbSh2YWx1ZSkuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSB7CiAgICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb25lb2ZOZXN0ZWRNZXNzYWdlMkJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxMTc7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG9uZW9mX25lc3RlZF9tZXNzYWdlMiA9IDExNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mTmVzdGVkTWVzc2FnZTIoKSB7CiAgICAgICAgaWYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNykgewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDExNykgewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG9uZW9mX25lc3RlZF9tZXNzYWdlMiA9IDExNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5CdWlsZGVyIGdldE9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBnZXRPbmVvZk5lc3RlZE1lc3NhZ2UyRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMiBvbmVvZl9uZXN0ZWRfbWVzc2FnZTIgPSAxMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMk9yQnVpbGRlciBnZXRPbmVvZk5lc3RlZE1lc3NhZ2UyT3JCdWlsZGVyKCkgewogICAgICAgIGlmICgob25lb2ZGaWVsZENhc2VfID09IDExNykgJiYgKG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyAhPSBudWxsKSkgewogICAgICAgICAgcmV0dXJuIG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMTE3KSB7CiAgICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMikgb25lb2ZGaWVsZF87CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyIG9uZW9mX25lc3RlZF9tZXNzYWdlMiA9IDExNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTJPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T25lb2ZOZXN0ZWRNZXNzYWdlMkZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob25lb2ZOZXN0ZWRNZXNzYWdlMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghKG9uZW9mRmllbGRDYXNlXyA9PSAxMTcpKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMi5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uZW9mTmVzdGVkTWVzc2FnZTJCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTIuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlMk9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UyKSBvbmVvZkZpZWxkXywKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMTE3OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBvbmVvZk5lc3RlZE1lc3NhZ2UyQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGRlY2VwdGl2ZWx5TmFtZWRMaXN0XyA7CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBUZXN0cyB0b1N0cmluZyBmb3Igbm9uLXJlcGVhdGVkIGZpZWxkcyB3aXRoIGEgbGlzdCBzdWZmaXgKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlY2VwdGl2ZWx5X25hbWVkX2xpc3QgPSAxMTY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlY2VwdGl2ZWx5TmFtZWRMaXN0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzRGVjZXB0aXZlbHlOYW1lZExpc3QoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQyXyAmIDB4MDAwMDQwMDApICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBUZXN0cyB0b1N0cmluZyBmb3Igbm9uLXJlcGVhdGVkIGZpZWxkcyB3aXRoIGEgbGlzdCBzdWZmaXgKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlY2VwdGl2ZWx5X25hbWVkX2xpc3QgPSAxMTY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBkZWNlcHRpdmVseU5hbWVkTGlzdC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXREZWNlcHRpdmVseU5hbWVkTGlzdCgpIHsKICAgICAgICByZXR1cm4gZGVjZXB0aXZlbHlOYW1lZExpc3RfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8cHJlPgogICAgICAgKiBUZXN0cyB0b1N0cmluZyBmb3Igbm9uLXJlcGVhdGVkIGZpZWxkcyB3aXRoIGEgbGlzdCBzdWZmaXgKICAgICAgICogPC9wcmU+CiAgICAgICAqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGRlY2VwdGl2ZWx5X25hbWVkX2xpc3QgPSAxMTY7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlY2VwdGl2ZWx5TmFtZWRMaXN0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RGVjZXB0aXZlbHlOYW1lZExpc3QoaW50IHZhbHVlKSB7CgogICAgICAgIGRlY2VwdGl2ZWx5TmFtZWRMaXN0XyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMl8gfD0gMHgwMDAwNDAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPHByZT4KICAgICAgICogVGVzdHMgdG9TdHJpbmcgZm9yIG5vbi1yZXBlYXRlZCBmaWVsZHMgd2l0aCBhIGxpc3Qgc3VmZml4CiAgICAgICAqIDwvcHJlPgogICAgICAgKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZWNlcHRpdmVseV9uYW1lZF9saXN0ID0gMTE2OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJEZWNlcHRpdmVseU5hbWVkTGlzdCgpIHsKICAgICAgICBiaXRGaWVsZDJfID0gKGJpdEZpZWxkMl8gJiB+MHgwMDAwNDAwMCk7CiAgICAgICAgZGVjZXB0aXZlbHlOYW1lZExpc3RfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEFsbFR5cGVzTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0QWxsVHlwZXNMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdEFsbFR5cGVzTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RBbGxUeXBlc0xpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEFsbFR5cGVzTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIEZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0MoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYy4KICAgICAqLwogICAgaW50IGdldEMoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgRm9yZWlnbk1lc3NhZ2VMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSkKICAgICAgRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBGb3JlaWduTWVzc2FnZUxpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgRm9yZWlnbk1lc3NhZ2VMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgRm9yZWlnbk1lc3NhZ2VMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IEZvcmVpZ25NZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IENfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgaW50IGNfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBjIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzQygpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEMoKSB7CiAgICAgIHJldHVybiBjXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGNfKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBjXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlKSBvYmo7CgogICAgICBpZiAoaGFzQygpICE9IG90aGVyLmhhc0MoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzQygpKSB7CiAgICAgICAgaWYgKGdldEMoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRDKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNDKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBDX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRDKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBjXyA9IDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmNfID0gY187CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzQygpKSB7CiAgICAgICAgICBzZXRDKG90aGVyLmdldEMoKSk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgODogewogICAgICAgICAgICAgICAgY18gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IGNfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGMgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBjIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzQygpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGMgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRDKCkgewogICAgICAgIHJldHVybiBjXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGMgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRDKGludCB2YWx1ZSkgewoKICAgICAgICBjXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckMoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGNfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPEZvcmVpZ25NZXNzYWdlTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxGb3JlaWduTWVzc2FnZUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBGb3JlaWduTWVzc2FnZUxpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxGb3JlaWduTWVzc2FnZUxpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8Rm9yZWlnbk1lc3NhZ2VMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0UGFja2VkVHlwZXNMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRUeXBlc0xpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA5MCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkSW50MzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRQYWNrZWRJbnQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gOTAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEludDMyLgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkSW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA5MCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRJbnQzMihpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEludDY0LgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4gZ2V0UGFja2VkSW50NjRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRJbnQ2NC4KICAgICAqLwogICAgaW50IGdldFBhY2tlZEludDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkSW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBsb25nIGdldFBhY2tlZEludDY0KGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRVaW50MzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRQYWNrZWRVaW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFVpbnQzMi4KICAgICAqLwogICAgaW50IGdldFBhY2tlZFVpbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkVWludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFBhY2tlZFVpbnQzMihpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkVWludDY0LgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4gZ2V0UGFja2VkVWludDY0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRVaW50NjQuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRVaW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFVpbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGxvbmcgZ2V0UGFja2VkVWludDY0KGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTaW50MzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRQYWNrZWRTaW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiBwYWNrZWRfc2ludDMyID0gOTQgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNpbnQzMi4KICAgICAqLwogICAgaW50IGdldFBhY2tlZFNpbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiBwYWNrZWRfc2ludDMyID0gOTQgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkU2ludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFBhY2tlZFNpbnQzMihpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHBhY2tlZF9zaW50NjQgPSA5NSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkU2ludDY0LgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4gZ2V0UGFja2VkU2ludDY0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRTaW50NjQuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRTaW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFNpbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGxvbmcgZ2V0UGFja2VkU2ludDY0KGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEZpeGVkMzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRQYWNrZWRGaXhlZDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEZpeGVkMzIuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRGaXhlZDMyQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkRml4ZWQzMihpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRGaXhlZDY0LgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4gZ2V0UGFja2VkRml4ZWQ2NExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRGaXhlZDY0LgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkRml4ZWQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRGaXhlZDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgbG9uZyBnZXRQYWNrZWRGaXhlZDY0KGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiBwYWNrZWRfc2ZpeGVkMzIgPSA5OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkU2ZpeGVkMzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRQYWNrZWRTZml4ZWQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcGFja2VkX3NmaXhlZDMyID0gOTggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNmaXhlZDMyLgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkU2ZpeGVkMzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiBwYWNrZWRfc2ZpeGVkMzIgPSA5OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRTZml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRTZml4ZWQzMihpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFNmaXhlZDY0LgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4gZ2V0UGFja2VkU2ZpeGVkNjRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRTZml4ZWQ2NC4KICAgICAqLwogICAgaW50IGdldFBhY2tlZFNmaXhlZDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkU2ZpeGVkNjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBsb25nIGdldFBhY2tlZFNmaXhlZDY0KGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEZsb2F0LgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRmxvYXQ+IGdldFBhY2tlZEZsb2F0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEZsb2F0LgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkRmxvYXRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkRmxvYXQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBmbG9hdCBnZXRQYWNrZWRGbG9hdChpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZERvdWJsZS4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkRvdWJsZT4gZ2V0UGFja2VkRG91YmxlTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcGFja2VkX2RvdWJsZSA9IDEwMSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkRG91YmxlLgogICAgICovCiAgICBpbnQgZ2V0UGFja2VkRG91YmxlQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkRG91YmxlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgZG91YmxlIGdldFBhY2tlZERvdWJsZShpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCBwYWNrZWRfYm9vbCA9IDEwMiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkQm9vbC4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkJvb2xlYW4+IGdldFBhY2tlZEJvb2xMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEJvb2wuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRCb29sQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCBwYWNrZWRfYm9vbCA9IDEwMiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRCb29sIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgYm9vbGVhbiBnZXRQYWNrZWRCb29sKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHBhY2tlZF9lbnVtID0gMTAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRFbnVtLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IGdldFBhY2tlZEVudW1MaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEVudW0uCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRFbnVtQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRFbnVtIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldFBhY2tlZEVudW0oaW50IGluZGV4KTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZFR5cGVzTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RQYWNrZWRUeXBlc0xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZFR5cGVzTGl0ZSkKICAgICAgVGVzdFBhY2tlZFR5cGVzTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdFBhY2tlZFR5cGVzTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0UGFja2VkVHlwZXNMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdFBhY2tlZFR5cGVzTGl0ZSgpIHsKICAgICAgcGFja2VkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHBhY2tlZEludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgcGFja2VkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwYWNrZWRVaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwYWNrZWRTaW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHBhY2tlZFNpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHBhY2tlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHBhY2tlZEZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwYWNrZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcGFja2VkU2ZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwYWNrZWRGbG9hdF8gPSBlbXB0eUZsb2F0TGlzdCgpOwogICAgICBwYWNrZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgIHBhY2tlZEJvb2xfID0gZW1wdHlCb29sZWFuTGlzdCgpOwogICAgICBwYWNrZWRFbnVtXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0UGFja2VkVHlwZXNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYWNrZWRUeXBlc0xpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhY2tlZFR5cGVzTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDkwOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCBwYWNrZWRJbnQzMl8gPQogICAgICAgIGVtcHR5SW50TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA5MCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkSW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRQYWNrZWRJbnQzMkxpc3QoKSB7CiAgICAgIHJldHVybiBwYWNrZWRJbnQzMl87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRJbnQzMi4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkSW50MzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gOTAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZEludDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcGFja2VkSW50MzJfLmdldEludChpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRJbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfSU5UNjRfRklFTERfTlVNQkVSID0gOTE7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCBwYWNrZWRJbnQ2NF8gPQogICAgICAgIGVtcHR5TG9uZ0xpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgZ2V0UGFja2VkSW50NjRMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkSW50NjRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCBwYWNrZWRfaW50NjQgPSA5MSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkSW50NjQuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkSW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEludDY0Xy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGxvbmcgZ2V0UGFja2VkSW50NjQoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRJbnQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRJbnQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfVUlOVDMyX0ZJRUxEX05VTUJFUiA9IDkyOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCBwYWNrZWRVaW50MzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHBhY2tlZF91aW50MzIgPSA5MiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkVWludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UGFja2VkVWludDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFVpbnQzMl87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFVpbnQzMi4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRVaW50MzJDb3VudCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFVpbnQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFVpbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkVWludDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcGFja2VkVWludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkVWludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9VSU5UNjRfRklFTERfTlVNQkVSID0gOTM7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCBwYWNrZWRVaW50NjRfID0KICAgICAgICBlbXB0eUxvbmdMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCBwYWNrZWRfdWludDY0ID0gOTMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFVpbnQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgIGdldFBhY2tlZFVpbnQ2NExpc3QoKSB7CiAgICAgIHJldHVybiBwYWNrZWRVaW50NjRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRVaW50NjQuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkVWludDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRVaW50NjRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRVaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgbG9uZyBnZXRQYWNrZWRVaW50NjQoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRVaW50NjRfLmdldExvbmcoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkVWludDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9TSU5UMzJfRklFTERfTlVNQkVSID0gOTQ7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZFNpbnQzMl8gPQogICAgICAgIGVtcHR5SW50TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTaW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRQYWNrZWRTaW50MzJMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkU2ludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHBhY2tlZF9zaW50MzIgPSA5NCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkU2ludDMyLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZFNpbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkU2ludDMyXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiBwYWNrZWRfc2ludDMyID0gOTQgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkU2ludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRTaW50MzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRTaW50MzJfLmdldEludChpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRTaW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1NJTlQ2NF9GSUVMRF9OVU1CRVIgPSA5NTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHBhY2tlZFNpbnQ2NF8gPQogICAgICAgIGVtcHR5TG9uZ0xpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHBhY2tlZF9zaW50NjQgPSA5NSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkU2ludDY0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgZ2V0UGFja2VkU2ludDY0TGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNpbnQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCBwYWNrZWRfc2ludDY0ID0gOTUgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNpbnQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRTaW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNpbnQ2NF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFNpbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBsb25nIGdldFBhY2tlZFNpbnQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNpbnQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRTaW50NjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0ZJWEVEMzJfRklFTERfTlVNQkVSID0gOTY7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZEZpeGVkMzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRGaXhlZDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UGFja2VkRml4ZWQzMkxpc3QoKSB7CiAgICAgIHJldHVybiBwYWNrZWRGaXhlZDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRGaXhlZDMyLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZEZpeGVkMzJDb3VudCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEZpeGVkMzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZEZpeGVkMzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRGaXhlZDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkRml4ZWQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfRklYRUQ2NF9GSUVMRF9OVU1CRVIgPSA5NzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHBhY2tlZEZpeGVkNjRfID0KICAgICAgICBlbXB0eUxvbmdMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkRml4ZWQ2NC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPgogICAgICAgIGdldFBhY2tlZEZpeGVkNjRMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkRml4ZWQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkRml4ZWQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRGaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRGaXhlZDY0Xy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRGaXhlZDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGxvbmcgZ2V0UGFja2VkRml4ZWQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEZpeGVkNjRfLmdldExvbmcoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkRml4ZWQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfU0ZJWEVEMzJfRklFTERfTlVNQkVSID0gOTg7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZFNmaXhlZDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTZml4ZWQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFBhY2tlZFNmaXhlZDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNmaXhlZDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcGFja2VkX3NmaXhlZDMyID0gOTggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNmaXhlZDMyLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFBhY2tlZFNmaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQzMiBwYWNrZWRfc2ZpeGVkMzIgPSA5OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRTZml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkU2ZpeGVkMzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZFNmaXhlZDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9TRklYRUQ2NF9GSUVMRF9OVU1CRVIgPSA5OTsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxvbmdMaXN0IHBhY2tlZFNmaXhlZDY0XyA9CiAgICAgICAgZW1wdHlMb25nTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCBwYWNrZWRfc2ZpeGVkNjQgPSA5OSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkU2ZpeGVkNjQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICBnZXRQYWNrZWRTZml4ZWQ2NExpc3QoKSB7CiAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQ2NF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRTZml4ZWQ2NC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRTZml4ZWQ2NENvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkU2ZpeGVkNjRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkU2ZpeGVkNjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgbG9uZyBnZXRQYWNrZWRTZml4ZWQ2NChpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZFNmaXhlZDY0Xy5nZXRMb25nKGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZFNmaXhlZDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9GTE9BVF9GSUVMRF9OVU1CRVIgPSAxMDA7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5GbG9hdExpc3QgcGFja2VkRmxvYXRfID0KICAgICAgICBlbXB0eUZsb2F0TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmbG9hdCBwYWNrZWRfZmxvYXQgPSAxMDAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEZsb2F0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkZsb2F0PgogICAgICAgIGdldFBhY2tlZEZsb2F0TGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEZsb2F0XzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcGFja2VkX2Zsb2F0ID0gMTAwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRGbG9hdC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRGbG9hdENvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkRmxvYXRfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcGFja2VkX2Zsb2F0ID0gMTAwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEZsb2F0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGZsb2F0IGdldFBhY2tlZEZsb2F0KGludCBpbmRleCkgewogICAgICByZXR1cm4gcGFja2VkRmxvYXRfLmdldEZsb2F0KGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHBhY2tlZEZsb2F0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9ET1VCTEVfRklFTERfTlVNQkVSID0gMTAxOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRG91YmxlTGlzdCBwYWNrZWREb3VibGVfID0KICAgICAgICBlbXB0eURvdWJsZUxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZERvdWJsZS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgZ2V0UGFja2VkRG91YmxlTGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZERvdWJsZV87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSBwYWNrZWRfZG91YmxlID0gMTAxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWREb3VibGUuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkRG91YmxlQ291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWREb3VibGVfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkRG91YmxlIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGRvdWJsZSBnZXRQYWNrZWREb3VibGUoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiBwYWNrZWREb3VibGVfLmdldERvdWJsZShpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWREb3VibGVNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0JPT0xfRklFTERfTlVNQkVSID0gMTAyOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuQm9vbGVhbkxpc3QgcGFja2VkQm9vbF8gPQogICAgICAgIGVtcHR5Qm9vbGVhbkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCBwYWNrZWRfYm9vbCA9IDEwMiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkQm9vbC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgIGdldFBhY2tlZEJvb2xMaXN0KCkgewogICAgICByZXR1cm4gcGFja2VkQm9vbF87CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEJvb2wuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkQm9vbENvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkQm9vbF8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBib29sIHBhY2tlZF9ib29sID0gMTAyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEJvb2wgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgYm9vbGVhbiBnZXRQYWNrZWRCb29sKGludCBpbmRleCkgewogICAgICByZXR1cm4gcGFja2VkQm9vbF8uZ2V0Qm9vbGVhbihpbmRleCk7CiAgICB9CiAgICBwcml2YXRlIGludCBwYWNrZWRCb29sTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IC0xOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9FTlVNX0ZJRUxEX05VTUJFUiA9IDEwMzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gcGFja2VkRW51bV87CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPiBwYWNrZWRFbnVtX2NvbnZlcnRlcl8gPQogICAgICAgICAgICBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5MaXN0QWRhcHRlci5Db252ZXJ0ZXI8CiAgICAgICAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPigpIHsKICAgICAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGNvbnZlcnQoamF2YS5sYW5nLkludGVnZXIgZnJvbSkgewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIoZnJvbSk7CiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuRk9SRUlHTl9MSVRFX0ZPTyA6IHJlc3VsdDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH07CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEVudW0uCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IGdldFBhY2tlZEVudW1MaXN0KCkgewogICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTGlzdEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPihwYWNrZWRFbnVtXywgcGFja2VkRW51bV9jb252ZXJ0ZXJfKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkRW51bS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRQYWNrZWRFbnVtQ291bnQoKSB7CiAgICAgIHJldHVybiBwYWNrZWRFbnVtXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcGFja2VkRW51bSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgZ2V0UGFja2VkRW51bShpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEVudW1fY29udmVydGVyXy5jb252ZXJ0KHBhY2tlZEVudW1fLmdldChpbmRleCkpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkRW51bU1lbW9pemVkU2VyaWFsaXplZFNpemU7CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBnZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBpZiAoZ2V0UGFja2VkSW50MzJMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDcyMik7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkSW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZEludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZUludDMyTm9UYWcocGFja2VkSW50MzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZEludDY0TGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg3MzApOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZEludDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRJbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQ2NE5vVGFnKHBhY2tlZEludDY0Xy5nZXRMb25nKGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkVWludDMyTGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg3MzgpOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZFVpbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkVWludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZFVpbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkVWludDY0TGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg3NDYpOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZFVpbnQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkVWludDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQ2NE5vVGFnKHBhY2tlZFVpbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZFNpbnQzMkxpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoNzU0KTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhwYWNrZWRTaW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZFNpbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVTSW50MzJOb1RhZyhwYWNrZWRTaW50MzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZFNpbnQ2NExpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoNzYyKTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhwYWNrZWRTaW50NjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZFNpbnQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVTSW50NjROb1RhZyhwYWNrZWRTaW50NjRfLmdldExvbmcoaSkpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRGaXhlZDMyTGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg3NzApOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZEZpeGVkMzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZEZpeGVkMzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRml4ZWQzMk5vVGFnKHBhY2tlZEZpeGVkMzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZEZpeGVkNjRMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDc3OCk7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkRml4ZWQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkRml4ZWQ2NF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVGaXhlZDY0Tm9UYWcocGFja2VkRml4ZWQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZFNmaXhlZDMyTGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg3ODYpOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZFNmaXhlZDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRTZml4ZWQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVTRml4ZWQzMk5vVGFnKHBhY2tlZFNmaXhlZDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRTZml4ZWQ2NExpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoNzk0KTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhwYWNrZWRTZml4ZWQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkU2ZpeGVkNjRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlU0ZpeGVkNjROb1RhZyhwYWNrZWRTZml4ZWQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZEZsb2F0TGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyg4MDIpOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZEZsb2F0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRGbG9hdF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVGbG9hdE5vVGFnKHBhY2tlZEZsb2F0Xy5nZXRGbG9hdChpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZERvdWJsZUxpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoODEwKTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhwYWNrZWREb3VibGVNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhY2tlZERvdWJsZV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVEb3VibGVOb1RhZyhwYWNrZWREb3VibGVfLmdldERvdWJsZShpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZEJvb2xMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDgxOCk7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkQm9vbE1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkQm9vbF8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVCb29sTm9UYWcocGFja2VkQm9vbF8uZ2V0Qm9vbGVhbihpKSk7CiAgICAgIH0KICAgICAgaWYgKGdldFBhY2tlZEVudW1MaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDgyNik7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocGFja2VkRW51bU1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkRW51bV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtTm9UYWcocGFja2VkRW51bV8uZ2V0KGkpKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhwYWNrZWRJbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZEludDMyTGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZEludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkSW50NjRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlSW50NjRTaXplTm9UYWcocGFja2VkSW50NjRfLmdldExvbmcoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkSW50NjRMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkSW50NjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRVaW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlVUludDMyU2l6ZU5vVGFnKHBhY2tlZFVpbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZFVpbnQzMkxpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICBwYWNrZWRVaW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRVaW50NjRfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlVUludDY0U2l6ZU5vVGFnKHBhY2tlZFVpbnQ2NF8uZ2V0TG9uZyhpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRVaW50NjRMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkVWludDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkU2ludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZVNJbnQzMlNpemVOb1RhZyhwYWNrZWRTaW50MzJfLmdldEludChpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRTaW50MzJMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkU2ludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkU2ludDY0Xy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZVNJbnQ2NFNpemVOb1RhZyhwYWNrZWRTaW50NjRfLmdldExvbmcoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkU2ludDY0TGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZFNpbnQ2NE1lbW9pemVkU2VyaWFsaXplZFNpemUgPSBkYXRhU2l6ZTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDQgKiBnZXRQYWNrZWRGaXhlZDMyTGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkRml4ZWQzMkxpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICBwYWNrZWRGaXhlZDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gOCAqIGdldFBhY2tlZEZpeGVkNjRMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRGaXhlZDY0TGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZEZpeGVkNjRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZGF0YVNpemUgPSA0ICogZ2V0UGFja2VkU2ZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRTZml4ZWQzMkxpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICBwYWNrZWRTZml4ZWQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSBkYXRhU2l6ZTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDggKiBnZXRQYWNrZWRTZml4ZWQ2NExpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZFNmaXhlZDY0TGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZFNmaXhlZDY0TWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gNCAqIGdldFBhY2tlZEZsb2F0TGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkRmxvYXRMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcGFja2VkRmxvYXRNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gZGF0YVNpemU7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZGF0YVNpemUgPSA4ICogZ2V0UGFja2VkRG91YmxlTGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkRG91YmxlTGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZERvdWJsZU1lbW9pemVkU2VyaWFsaXplZFNpemUgPSBkYXRhU2l6ZTsKICAgICAgfQogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDEgKiBnZXRQYWNrZWRCb29sTGlzdCgpLnNpemUoKTsKICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UGFja2VkQm9vbExpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICBwYWNrZWRCb29sTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFja2VkRW51bV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZU5vVGFnKHBhY2tlZEVudW1fLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRQYWNrZWRFbnVtTGlzdCgpLmlzRW1wdHkoKSkgeyAgc2l6ZSArPSAyOwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlVUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9cGFja2VkRW51bU1lbW9pemVkU2VyaWFsaXplZFNpemUgPSBkYXRhU2l6ZTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUpIG9iajsKCiAgICAgIGlmICghZ2V0UGFja2VkSW50MzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkSW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkSW50NjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkSW50NjRMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkVWludDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZFVpbnQzMkxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRQYWNrZWRVaW50NjRMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkVWludDY0TGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFBhY2tlZFNpbnQzMkxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRQYWNrZWRTaW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkU2ludDY0TGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZFNpbnQ2NExpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRQYWNrZWRGaXhlZDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZEZpeGVkMzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkRml4ZWQ2NExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRQYWNrZWRGaXhlZDY0TGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFBhY2tlZFNmaXhlZDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZFNmaXhlZDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFBhY2tlZFNmaXhlZDY0TGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZFNmaXhlZDY0TGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFBhY2tlZEZsb2F0TGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBhY2tlZEZsb2F0TGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFBhY2tlZERvdWJsZUxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRQYWNrZWREb3VibGVMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkQm9vbExpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRQYWNrZWRCb29sTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIXBhY2tlZEVudW1fLmVxdWFscyhvdGhlci5wYWNrZWRFbnVtXykpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoZ2V0UGFja2VkSW50MzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGFja2VkSW50MzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkSW50NjRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9JTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGFja2VkSW50NjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkVWludDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfVUlOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRVaW50MzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkVWludDY0Q291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfVUlOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRVaW50NjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkU2ludDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfU0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRTaW50MzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkU2ludDY0Q291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfU0lOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRTaW50NjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRml4ZWQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFBhY2tlZEZpeGVkMzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRml4ZWQ2NENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFBhY2tlZEZpeGVkNjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkU2ZpeGVkMzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9TRklYRUQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGFja2VkU2ZpeGVkMzJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkU2ZpeGVkNjRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9TRklYRUQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGFja2VkU2ZpeGVkNjRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRmxvYXRDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFBBQ0tFRF9GTE9BVF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGFja2VkRmxvYXRMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRG91YmxlQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBQQUNLRURfRE9VQkxFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWREb3VibGVMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkQm9vbENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0JPT0xfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFBhY2tlZEJvb2xMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UGFja2VkRW51bUNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIHBhY2tlZEVudW1fLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkVHlwZXNMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZFR5cGVzTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBwYWNrZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBwYWNrZWRJbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcGFja2VkVWludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHBhY2tlZFVpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcGFja2VkU2ludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHBhY2tlZFNpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcGFja2VkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBwYWNrZWRGaXhlZDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICBwYWNrZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBwYWNrZWRTZml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgcGFja2VkRmxvYXRfID0gZW1wdHlGbG9hdExpc3QoKTsKICAgICAgICBwYWNrZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgICAgcGFja2VkQm9vbF8gPSBlbXB0eUJvb2xlYW5MaXN0KCk7CiAgICAgICAgcGFja2VkRW51bV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDIwMDApOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhY2tlZFR5cGVzTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUodGhpcyk7CiAgICAgICAgYnVpbGRQYXJ0aWFsUmVwZWF0ZWRGaWVsZHMocmVzdWx0KTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsUmVwZWF0ZWRGaWVsZHMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSByZXN1bHQpIHsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZEVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocGFja2VkRW51bV8pOwogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDIwMDApOwogICAgICAgIH0KICAgICAgICByZXN1bHQucGFja2VkRW51bV8gPSBwYWNrZWRFbnVtXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRJbnQzMl8gPSBwYWNrZWRJbnQzMl87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICBwYWNrZWRJbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZEludDY0XyA9IHBhY2tlZEludDY0XzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZFVpbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZFVpbnQzMl8gPSBwYWNrZWRVaW50MzJfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgICAgcGFja2VkVWludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucGFja2VkVWludDY0XyA9IHBhY2tlZFVpbnQ2NF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgICBwYWNrZWRTaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRTaW50MzJfID0gcGFja2VkU2ludDMyXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZFNpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZFNpbnQ2NF8gPSBwYWNrZWRTaW50NjRfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkRml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZEZpeGVkMzJfID0gcGFja2VkRml4ZWQzMl87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgICBwYWNrZWRGaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucGFja2VkRml4ZWQ2NF8gPSBwYWNrZWRGaXhlZDY0XzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZFNmaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucGFja2VkU2ZpeGVkMzJfID0gcGFja2VkU2ZpeGVkMzJfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMjAwKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkU2ZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5wYWNrZWRTZml4ZWQ2NF8gPSBwYWNrZWRTZml4ZWQ2NF87CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDA0MDApICE9IDApKSB7CiAgICAgICAgICBwYWNrZWRGbG9hdF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZEZsb2F0XyA9IHBhY2tlZEZsb2F0XzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDgwMCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZERvdWJsZV8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZERvdWJsZV8gPSBwYWNrZWREb3VibGVfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAxMDAwKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkQm9vbF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgcmVzdWx0LnBhY2tlZEJvb2xfID0gcGFja2VkQm9vbF87CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmICghb3RoZXIucGFja2VkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkSW50MzJfID0gb3RoZXIucGFja2VkSW50MzJfOwogICAgICAgICAgICBwYWNrZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRJbnQzMl8uYWRkQWxsKG90aGVyLnBhY2tlZEludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRJbnQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkSW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWRJbnQ2NF8gPSBvdGhlci5wYWNrZWRJbnQ2NF87CiAgICAgICAgICAgIHBhY2tlZEludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZEludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZEludDY0Xy5hZGRBbGwob3RoZXIucGFja2VkSW50NjRfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnBhY2tlZFVpbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkVWludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkVWludDMyXyA9IG90aGVyLnBhY2tlZFVpbnQzMl87CiAgICAgICAgICAgIHBhY2tlZFVpbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRVaW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgcGFja2VkVWludDMyXy5hZGRBbGwob3RoZXIucGFja2VkVWludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRVaW50NjRfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZFVpbnQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZFVpbnQ2NF8gPSBvdGhlci5wYWNrZWRVaW50NjRfOwogICAgICAgICAgICBwYWNrZWRVaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkVWludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZFVpbnQ2NF8uYWRkQWxsKG90aGVyLnBhY2tlZFVpbnQ2NF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkU2ludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChwYWNrZWRTaW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWRTaW50MzJfID0gb3RoZXIucGFja2VkU2ludDMyXzsKICAgICAgICAgICAgcGFja2VkU2ludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZFNpbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRTaW50MzJfLmFkZEFsbChvdGhlci5wYWNrZWRTaW50MzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnBhY2tlZFNpbnQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkU2ludDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkU2ludDY0XyA9IG90aGVyLnBhY2tlZFNpbnQ2NF87CiAgICAgICAgICAgIHBhY2tlZFNpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICAgICAgcGFja2VkU2ludDY0Xy5hZGRBbGwob3RoZXIucGFja2VkU2ludDY0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRGaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChwYWNrZWRGaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkRml4ZWQzMl8gPSBvdGhlci5wYWNrZWRGaXhlZDMyXzsKICAgICAgICAgICAgcGFja2VkRml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZEZpeGVkMzJfLmFkZEFsbChvdGhlci5wYWNrZWRGaXhlZDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRGaXhlZDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChwYWNrZWRGaXhlZDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkRml4ZWQ2NF8gPSBvdGhlci5wYWNrZWRGaXhlZDY0XzsKICAgICAgICAgICAgcGFja2VkRml4ZWQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRGaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZEZpeGVkNjRfLmFkZEFsbChvdGhlci5wYWNrZWRGaXhlZDY0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWRTZml4ZWQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkU2ZpeGVkMzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBwYWNrZWRTZml4ZWQzMl8gPSBvdGhlci5wYWNrZWRTZml4ZWQzMl87CiAgICAgICAgICAgIHBhY2tlZFNmaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZFNmaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZFNmaXhlZDMyXy5hZGRBbGwob3RoZXIucGFja2VkU2ZpeGVkMzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAoIW90aGVyLnBhY2tlZFNmaXhlZDY0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChwYWNrZWRTZml4ZWQ2NF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZFNmaXhlZDY0XyA9IG90aGVyLnBhY2tlZFNmaXhlZDY0XzsKICAgICAgICAgICAgcGFja2VkU2ZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICAgICAgcGFja2VkU2ZpeGVkNjRfLmFkZEFsbChvdGhlci5wYWNrZWRTZml4ZWQ2NF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkRmxvYXRfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZEZsb2F0Xy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkRmxvYXRfID0gb3RoZXIucGFja2VkRmxvYXRfOwogICAgICAgICAgICBwYWNrZWRGbG9hdF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRGbG9hdElzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRGbG9hdF8uYWRkQWxsKG90aGVyLnBhY2tlZEZsb2F0Xyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFvdGhlci5wYWNrZWREb3VibGVfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZERvdWJsZV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZERvdWJsZV8gPSBvdGhlci5wYWNrZWREb3VibGVfOwogICAgICAgICAgICBwYWNrZWREb3VibGVfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkRG91YmxlSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHBhY2tlZERvdWJsZV8uYWRkQWxsKG90aGVyLnBhY2tlZERvdWJsZV8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkQm9vbF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkQm9vbF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZEJvb2xfID0gb3RoZXIucGFja2VkQm9vbF87CiAgICAgICAgICAgIHBhY2tlZEJvb2xfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUGFja2VkQm9vbElzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRCb29sXy5hZGRBbGwob3RoZXIucGFja2VkQm9vbF8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkRW51bV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocGFja2VkRW51bV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHBhY2tlZEVudW1fID0gb3RoZXIucGFja2VkRW51bV87CiAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVBhY2tlZEVudW1Jc011dGFibGUoKTsKICAgICAgICAgICAgcGFja2VkRW51bV8uYWRkQWxsKG90aGVyLnBhY2tlZEVudW1fKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDcyMDogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRJbnQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDcyMAogICAgICAgICAgICAgIGNhc2UgNzIyOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHBhY2tlZEludDMyXy5hZGRJbnQoaW5wdXQucmVhZEludDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDcyMgogICAgICAgICAgICAgIGNhc2UgNzI4OiB7CiAgICAgICAgICAgICAgICBsb25nIHYgPSBpbnB1dC5yZWFkSW50NjQoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRJbnQ2NF8uYWRkTG9uZyh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3MjgKICAgICAgICAgICAgICBjYXNlIDczMDogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRJbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRJbnQ2NF8uYWRkTG9uZyhpbnB1dC5yZWFkSW50NjQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzMwCiAgICAgICAgICAgICAgY2FzZSA3MzY6IHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5wdXQucmVhZFVJbnQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRVaW50MzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3MzYKICAgICAgICAgICAgICBjYXNlIDczODogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRVaW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkVWludDMyXy5hZGRJbnQoaW5wdXQucmVhZFVJbnQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3MzgKICAgICAgICAgICAgICBjYXNlIDc0NDogewogICAgICAgICAgICAgICAgbG9uZyB2ID0gaW5wdXQucmVhZFVJbnQ2NCgpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkVWludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRVaW50NjRfLmFkZExvbmcodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzQ0CiAgICAgICAgICAgICAgY2FzZSA3NDY6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkVWludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHBhY2tlZFVpbnQ2NF8uYWRkTG9uZyhpbnB1dC5yZWFkVUludDY0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc0NgogICAgICAgICAgICAgIGNhc2UgNzUyOiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRTSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZFNpbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkU2ludDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzUyCiAgICAgICAgICAgICAgY2FzZSA3NTQ6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHBhY2tlZFNpbnQzMl8uYWRkSW50KGlucHV0LnJlYWRTSW50MzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzU0CiAgICAgICAgICAgICAgY2FzZSA3NjA6IHsKICAgICAgICAgICAgICAgIGxvbmcgdiA9IGlucHV0LnJlYWRTSW50NjQoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZFNpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkU2ludDY0Xy5hZGRMb25nKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc2MAogICAgICAgICAgICAgIGNhc2UgNzYyOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZFNpbnQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRTaW50NjRfLmFkZExvbmcoaW5wdXQucmVhZFNJbnQ2NCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3NjIKICAgICAgICAgICAgICBjYXNlIDc3MzogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkRml4ZWQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkRml4ZWQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc3MwogICAgICAgICAgICAgIGNhc2UgNzcwOiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQzMklzTXV0YWJsZShhbGxvYyAvIDQpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRGaXhlZDMyXy5hZGRJbnQoaW5wdXQucmVhZEZpeGVkMzIoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzcwCiAgICAgICAgICAgICAgY2FzZSA3Nzc6IHsKICAgICAgICAgICAgICAgIGxvbmcgdiA9IGlucHV0LnJlYWRGaXhlZDY0KCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRGaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRGaXhlZDY0Xy5hZGRMb25nKHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc3NwogICAgICAgICAgICAgIGNhc2UgNzc4OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgbGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIGludCBhbGxvYyA9IGxlbmd0aCA+IDQwOTYgPyA0MDk2IDogbGVuZ3RoOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQ2NElzTXV0YWJsZShhbGxvYyAvIDgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRGaXhlZDY0Xy5hZGRMb25nKGlucHV0LnJlYWRGaXhlZDY0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc3OAogICAgICAgICAgICAgIGNhc2UgNzg5OiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRTRml4ZWQzMigpOwogICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHBhY2tlZFNmaXhlZDMyXy5hZGRJbnQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzg5CiAgICAgICAgICAgICAgY2FzZSA3ODY6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRTZml4ZWQzMklzTXV0YWJsZShhbGxvYyAvIDQpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRTZml4ZWQzMl8uYWRkSW50KGlucHV0LnJlYWRTRml4ZWQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA3ODYKICAgICAgICAgICAgICBjYXNlIDc5MzogewogICAgICAgICAgICAgICAgbG9uZyB2ID0gaW5wdXQucmVhZFNGaXhlZDY0KCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRTZml4ZWQ2NElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkU2ZpeGVkNjRfLmFkZExvbmcodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzkzCiAgICAgICAgICAgICAgY2FzZSA3OTQ6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRTZml4ZWQ2NElzTXV0YWJsZShhbGxvYyAvIDgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRTZml4ZWQ2NF8uYWRkTG9uZyhpbnB1dC5yZWFkU0ZpeGVkNjQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNzk0CiAgICAgICAgICAgICAgY2FzZSA4MDU6IHsKICAgICAgICAgICAgICAgIGZsb2F0IHYgPSBpbnB1dC5yZWFkRmxvYXQoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEZsb2F0SXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRGbG9hdF8uYWRkRmxvYXQodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODA1CiAgICAgICAgICAgICAgY2FzZSA4MDI6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRGbG9hdElzTXV0YWJsZShhbGxvYyAvIDQpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRGbG9hdF8uYWRkRmxvYXQoaW5wdXQucmVhZEZsb2F0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgwMgogICAgICAgICAgICAgIGNhc2UgODA5OiB7CiAgICAgICAgICAgICAgICBkb3VibGUgdiA9IGlucHV0LnJlYWREb3VibGUoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZERvdWJsZUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgcGFja2VkRG91YmxlXy5hZGREb3VibGUodik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODA5CiAgICAgICAgICAgICAgY2FzZSA4MTA6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWREb3VibGVJc011dGFibGUoYWxsb2MgLyA4KTsKICAgICAgICAgICAgICAgIHdoaWxlIChpbnB1dC5nZXRCeXRlc1VudGlsTGltaXQoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgcGFja2VkRG91YmxlXy5hZGREb3VibGUoaW5wdXQucmVhZERvdWJsZSgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4MTAKICAgICAgICAgICAgICBjYXNlIDgxNjogewogICAgICAgICAgICAgICAgYm9vbGVhbiB2ID0gaW5wdXQucmVhZEJvb2woKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEJvb2xJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHBhY2tlZEJvb2xfLmFkZEJvb2xlYW4odik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODE2CiAgICAgICAgICAgICAgY2FzZSA4MTg6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgaW50IGFsbG9jID0gbGVuZ3RoID4gNDA5NiA/IDQwOTYgOiBsZW5ndGg7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRCb29sSXNNdXRhYmxlKGFsbG9jIC8gMSk7CiAgICAgICAgICAgICAgICB3aGlsZSAoaW5wdXQuZ2V0Qnl0ZXNVbnRpbExpbWl0KCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgIHBhY2tlZEJvb2xfLmFkZEJvb2xlYW4oaW5wdXQucmVhZEJvb2woKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChsaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODE4CiAgICAgICAgICAgICAgY2FzZSA4MjQ6IHsKICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCgxMDMsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgIHBhY2tlZEVudW1fLmFkZCh0bXBSYXcpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgyNAogICAgICAgICAgICAgIGNhc2UgODI2OiB7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gaW5wdXQucmVhZFJhd1ZhcmludDMyKCk7CiAgICAgICAgICAgICAgICBpbnQgb2xkTGltaXQgPSBpbnB1dC5wdXNoTGltaXQobGVuZ3RoKTsKICAgICAgICAgICAgICAgIHdoaWxlKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgICAgaWYgKHRtcFZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCgxMDMsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgZW5zdXJlUGFja2VkRW51bUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICAgIHBhY2tlZEVudW1fLmFkZCh0bXBSYXcpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpbnB1dC5wb3BMaW1pdChvbGRMaW1pdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODI2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkSW50MzJJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWRJbnQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZEludDMyXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRJbnQzMl8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UGFja2VkSW50MzJMaXN0KCkgewogICAgICAgIHBhY2tlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHBhY2tlZEludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gOTAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkSW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZEludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEludDMyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZEludDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gOTAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkSW50MzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEludDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkSW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRJbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkSW50MzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRJbnQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDkwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkSW50MzIoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRJbnQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gOTAgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRJbnQzMigpIHsKICAgICAgICBwYWNrZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCBwYWNrZWRJbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRJbnQ2NElzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZEludDY0Xy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkSW50NjRfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZEludDY0Xyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcGFja2VkSW50NjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRQYWNrZWRJbnQ2NExpc3QoKSB7CiAgICAgICAgcGFja2VkSW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcGFja2VkSW50NjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCBwYWNrZWRfaW50NjQgPSA5MSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRJbnQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkSW50NjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkSW50NjRfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEludDY0IGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBsb25nIGdldFBhY2tlZEludDY0KGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRJbnQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRJbnQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZEludDY0KAogICAgICAgICAgaW50IGluZGV4LCBsb25nIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkSW50NjRfLnNldExvbmcoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDY0IHBhY2tlZF9pbnQ2NCA9IDkxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkSW50NjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRJbnQ2NChsb25nIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkSW50NjRfLmFkZExvbmcodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50NjQgcGFja2VkX2ludDY0ID0gOTEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkSW50NjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRJbnQ2NCgKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkxvbmc+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVBhY2tlZEludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZEludDY0Xyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQ2NCBwYWNrZWRfaW50NjQgPSA5MSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZEludDY0KCkgewogICAgICAgIHBhY2tlZEludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZFVpbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZFVpbnQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZFVpbnQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZFVpbnQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkVWludDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHBhY2tlZF91aW50MzIgPSA5MiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRVaW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRQYWNrZWRVaW50MzJMaXN0KCkgewogICAgICAgIHBhY2tlZFVpbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRVaW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFVpbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkVWludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFVpbnQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50MzIgcGFja2VkX3VpbnQzMiA9IDkyIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRVaW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRVaW50MzIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFVpbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHBhY2tlZF91aW50MzIgPSA5MiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkVWludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkVWludDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkVWludDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRVaW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRVaW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZFVpbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZFVpbnQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQzMiBwYWNrZWRfdWludDMyID0gOTIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkVWludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkVWludDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkVWludDMySXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZFVpbnQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDMyIHBhY2tlZF91aW50MzIgPSA5MiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZFVpbnQzMigpIHsKICAgICAgICBwYWNrZWRVaW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcGFja2VkVWludDY0XyA9IGVtcHR5TG9uZ0xpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZFVpbnQ2NElzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZFVpbnQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZFVpbnQ2NF8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkVWludDY0Xyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRVaW50NjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRQYWNrZWRVaW50NjRMaXN0KCkgewogICAgICAgIHBhY2tlZFVpbnQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRVaW50NjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFVpbnQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkVWludDY0Q291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFVpbnQ2NF8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRVaW50NjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGxvbmcgZ2V0UGFja2VkVWludDY0KGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRVaW50NjRfLmdldExvbmcoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRVaW50NjQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWRVaW50NjQoCiAgICAgICAgICBpbnQgaW5kZXgsIGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkVWludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkVWludDY0Xy5zZXRMb25nKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCB1aW50NjQgcGFja2VkX3VpbnQ2NCA9IDkzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkVWludDY0IHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkVWludDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkVWludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkVWludDY0Xy5hZGRMb25nKHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHVpbnQ2NCBwYWNrZWRfdWludDY0ID0gOTMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkVWludDY0IHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkVWludDY0KAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkVWludDY0SXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZFVpbnQ2NF8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgdWludDY0IHBhY2tlZF91aW50NjQgPSA5MyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZFVpbnQ2NCgpIHsKICAgICAgICBwYWNrZWRVaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkU2ludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkU2ludDMySXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcGFja2VkU2ludDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkU2ludDMyXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRTaW50MzJfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFNpbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFBhY2tlZFNpbnQzMkxpc3QoKSB7CiAgICAgICAgcGFja2VkU2ludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNpbnQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiBwYWNrZWRfc2ludDMyID0gOTQgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkU2ludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRTaW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkU2ludDMyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQzMiBwYWNrZWRfc2ludDMyID0gOTQgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFNpbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZFNpbnQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcGFja2VkU2ludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRTaW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWRTaW50MzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRTaW50MzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRTaW50MzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHBhY2tlZF9zaW50MzIgPSA5NCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZFNpbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZFNpbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkU2ludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkU2ludDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDMyIHBhY2tlZF9zaW50MzIgPSA5NCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBwYWNrZWRTaW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRTaW50MzIoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRTaW50MzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcGFja2VkU2ludDMyXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50MzIgcGFja2VkX3NpbnQzMiA9IDk0IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGFja2VkU2ludDMyKCkgewogICAgICAgIHBhY2tlZFNpbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCBwYWNrZWRTaW50NjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkU2ludDY0SXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcGFja2VkU2ludDY0Xy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkU2ludDY0XyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRTaW50NjRfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFNpbnQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldFBhY2tlZFNpbnQ2NExpc3QoKSB7CiAgICAgICAgcGFja2VkU2ludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNpbnQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCBwYWNrZWRfc2ludDY0ID0gOTUgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkU2ludDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRTaW50NjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkU2ludDY0Xy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCBwYWNrZWRfc2ludDY0ID0gOTUgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZFNpbnQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgbG9uZyBnZXRQYWNrZWRTaW50NjQoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNpbnQ2NF8uZ2V0TG9uZyhpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCBwYWNrZWRfc2ludDY0ID0gOTUgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZFNpbnQ2NCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZFNpbnQ2NCgKICAgICAgICAgIGludCBpbmRleCwgbG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRTaW50NjRfLnNldExvbmcoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNpbnQ2NCBwYWNrZWRfc2ludDY0ID0gOTUgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRTaW50NjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRTaW50NjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRTaW50NjRfLmFkZExvbmcodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ludDY0IHBhY2tlZF9zaW50NjQgPSA5NSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBwYWNrZWRTaW50NjQgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRTaW50NjQoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRTaW50NjRJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcGFja2VkU2ludDY0Xyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzaW50NjQgcGFja2VkX3NpbnQ2NCA9IDk1IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGFja2VkU2ludDY0KCkgewogICAgICAgIHBhY2tlZFNpbnQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMjApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCBwYWNrZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkRml4ZWQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZEZpeGVkMzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRGaXhlZDMyXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRGaXhlZDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkRml4ZWQzMklzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXBhY2tlZEZpeGVkMzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRGaXhlZDMyXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRGaXhlZDMyXywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcGFja2VkX2ZpeGVkMzIgPSA5NiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRGaXhlZDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UGFja2VkRml4ZWQzMkxpc3QoKSB7CiAgICAgICAgcGFja2VkRml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRGaXhlZDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZEZpeGVkMzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZEZpeGVkMzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkRml4ZWQzMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRGaXhlZDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRGaXhlZDMyXy5nZXRJbnQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEZpeGVkMzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWRGaXhlZDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEZpeGVkMzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkRml4ZWQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZEZpeGVkMzIoaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRGaXhlZDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiBwYWNrZWRfZml4ZWQzMiA9IDk2IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZEZpeGVkMzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRGaXhlZDMyKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRGaXhlZDMyXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHBhY2tlZF9maXhlZDMyID0gOTYgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRGaXhlZDMyKCkgewogICAgICAgIHBhY2tlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwNDApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTG9uZ0xpc3QgcGFja2VkRml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRGaXhlZDY0SXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcGFja2VkRml4ZWQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZEZpeGVkNjRfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZEZpeGVkNjRfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRGaXhlZDY0SXNNdXRhYmxlKGludCBjYXBhY2l0eSkgewogICAgICAgIGlmICghcGFja2VkRml4ZWQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZEZpeGVkNjRfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZEZpeGVkNjRfLCBjYXBhY2l0eSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEZpeGVkNjQuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRQYWNrZWRGaXhlZDY0TGlzdCgpIHsKICAgICAgICBwYWNrZWRGaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHBhY2tlZEZpeGVkNjRfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHBhY2tlZF9maXhlZDY0ID0gOTcgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkRml4ZWQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkRml4ZWQ2NENvdW50KCkgewogICAgICAgIHJldHVybiBwYWNrZWRGaXhlZDY0Xy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkRml4ZWQ2NCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgbG9uZyBnZXRQYWNrZWRGaXhlZDY0KGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRGaXhlZDY0Xy5nZXRMb25nKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRGaXhlZDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkRml4ZWQ2NCgKICAgICAgICAgIGludCBpbmRleCwgbG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRGaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkRml4ZWQ2NF8uc2V0TG9uZyhpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQ2NCBwYWNrZWRfZml4ZWQ2NCA9IDk3IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkRml4ZWQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZEZpeGVkNjQobG9uZyB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRGaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkRml4ZWQ2NF8uYWRkTG9uZyh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDY0IHBhY2tlZF9maXhlZDY0ID0gOTcgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkRml4ZWQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZEZpeGVkNjQoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRGaXhlZDY0SXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZEZpeGVkNjRfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkNjQgcGFja2VkX2ZpeGVkNjQgPSA5NyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZEZpeGVkNjQoKSB7CiAgICAgICAgcGFja2VkRml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwODApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCBwYWNrZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZFNmaXhlZDMySXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcGFja2VkU2ZpeGVkMzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRTZml4ZWQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkU2ZpeGVkMzJfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRTZml4ZWQzMklzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXBhY2tlZFNmaXhlZDMyXy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkU2ZpeGVkMzJfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZFNmaXhlZDMyXywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZFNmaXhlZDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UGFja2VkU2ZpeGVkMzJMaXN0KCkgewogICAgICAgIHBhY2tlZFNmaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNmaXhlZDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcGFja2VkX3NmaXhlZDMyID0gOTggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkU2ZpeGVkMzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZFNmaXhlZDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNmaXhlZDMyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRTZml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZFNmaXhlZDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcGFja2VkX3NmaXhlZDMyID0gOTggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZFNmaXhlZDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkU2ZpeGVkMzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRTZml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZFNmaXhlZDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkU2ZpeGVkMzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRQYWNrZWRTZml4ZWQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRTZml4ZWQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDMyIHBhY2tlZF9zZml4ZWQzMiA9IDk4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZFNmaXhlZDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkU2ZpeGVkMzIoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRTZml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRTZml4ZWQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkMzIgcGFja2VkX3NmaXhlZDMyID0gOTggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRTZml4ZWQzMigpIHsKICAgICAgICBwYWNrZWRTZml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDEwMCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5Mb25nTGlzdCBwYWNrZWRTZml4ZWQ2NF8gPSBlbXB0eUxvbmdMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRTZml4ZWQ2NElzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXBhY2tlZFNmaXhlZDY0Xy5pc01vZGlmaWFibGUoKSkgewogICAgICAgICAgcGFja2VkU2ZpeGVkNjRfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZFNmaXhlZDY0Xyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkU2ZpeGVkNjRJc011dGFibGUoaW50IGNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFwYWNrZWRTZml4ZWQ2NF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZFNmaXhlZDY0XyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRTZml4ZWQ2NF8sIGNhcGFjaXR5KTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCBwYWNrZWRfc2ZpeGVkNjQgPSA5OSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRTZml4ZWQ2NC4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldFBhY2tlZFNmaXhlZDY0TGlzdCgpIHsKICAgICAgICBwYWNrZWRTZml4ZWQ2NF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQ2NF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHBhY2tlZFNmaXhlZDY0LgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRTZml4ZWQ2NENvdW50KCkgewogICAgICAgIHJldHVybiBwYWNrZWRTZml4ZWQ2NF8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCBwYWNrZWRfc2ZpeGVkNjQgPSA5OSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkU2ZpeGVkNjQgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGxvbmcgZ2V0UGFja2VkU2ZpeGVkNjQoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZFNmaXhlZDY0Xy5nZXRMb25nKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZFNmaXhlZDY0IHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkU2ZpeGVkNjQoCiAgICAgICAgICBpbnQgaW5kZXgsIGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRTZml4ZWQ2NF8uc2V0TG9uZyhpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgc2ZpeGVkNjQgcGFja2VkX3NmaXhlZDY0ID0gOTkgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRTZml4ZWQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZFNmaXhlZDY0KGxvbmcgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRTZml4ZWQ2NF8uYWRkTG9uZyh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBzZml4ZWQ2NCBwYWNrZWRfc2ZpeGVkNjQgPSA5OSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSBwYWNrZWRTZml4ZWQ2NCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZFNmaXhlZDY0KAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkU2ZpeGVkNjRJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcGFja2VkU2ZpeGVkNjRfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIHNmaXhlZDY0IHBhY2tlZF9zZml4ZWQ2NCA9IDk5IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGFja2VkU2ZpeGVkNjQoKSB7CiAgICAgICAgcGFja2VkU2ZpeGVkNjRfID0gZW1wdHlMb25nTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMjAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkZsb2F0TGlzdCBwYWNrZWRGbG9hdF8gPSBlbXB0eUZsb2F0TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkRmxvYXRJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWRGbG9hdF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZEZsb2F0XyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRGbG9hdF8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZEZsb2F0SXNNdXRhYmxlKGludCBjYXBhY2l0eSkgewogICAgICAgIGlmICghcGFja2VkRmxvYXRfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWRGbG9hdF8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkRmxvYXRfLCBjYXBhY2l0eSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcGFja2VkX2Zsb2F0ID0gMTAwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEZsb2F0LgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5GbG9hdD4KICAgICAgICAgIGdldFBhY2tlZEZsb2F0TGlzdCgpIHsKICAgICAgICBwYWNrZWRGbG9hdF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRGbG9hdF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHBhY2tlZF9mbG9hdCA9IDEwMCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRGbG9hdC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkRmxvYXRDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkRmxvYXRfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcGFja2VkX2Zsb2F0ID0gMTAwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRGbG9hdCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgZmxvYXQgZ2V0UGFja2VkRmxvYXQoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEZsb2F0Xy5nZXRGbG9hdChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHBhY2tlZF9mbG9hdCA9IDEwMCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkRmxvYXQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRQYWNrZWRGbG9hdCgKICAgICAgICAgIGludCBpbmRleCwgZmxvYXQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkRmxvYXRJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRGbG9hdF8uc2V0RmxvYXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHBhY2tlZF9mbG9hdCA9IDEwMCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZEZsb2F0IHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkRmxvYXQoZmxvYXQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkRmxvYXRJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRGbG9hdF8uYWRkRmxvYXQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZmxvYXQgcGFja2VkX2Zsb2F0ID0gMTAwIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZEZsb2F0IHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkRmxvYXQoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5GbG9hdD4gdmFsdWVzKSB7CiAgICAgICAgZW5zdXJlUGFja2VkRmxvYXRJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcGFja2VkRmxvYXRfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZsb2F0IHBhY2tlZF9mbG9hdCA9IDEwMCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZEZsb2F0KCkgewogICAgICAgIHBhY2tlZEZsb2F0XyA9IGVtcHR5RmxvYXRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDA0MDApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRG91YmxlTGlzdCBwYWNrZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWREb3VibGVJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWREb3VibGVfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICBwYWNrZWREb3VibGVfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZERvdWJsZV8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZERvdWJsZUlzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXBhY2tlZERvdWJsZV8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZERvdWJsZV8gPSBtYWtlTXV0YWJsZUNvcHkocGFja2VkRG91YmxlXywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSBwYWNrZWRfZG91YmxlID0gMTAxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZERvdWJsZS4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRG91YmxlPgogICAgICAgICAgZ2V0UGFja2VkRG91YmxlTGlzdCgpIHsKICAgICAgICBwYWNrZWREb3VibGVfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcGFja2VkRG91YmxlXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkRG91YmxlLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWREb3VibGVDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkRG91YmxlXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGRvdWJsZSBwYWNrZWRfZG91YmxlID0gMTAxIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWREb3VibGUgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICAgKi8KICAgICAgcHVibGljIGRvdWJsZSBnZXRQYWNrZWREb3VibGUoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZERvdWJsZV8uZ2V0RG91YmxlKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZERvdWJsZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZERvdWJsZSgKICAgICAgICAgIGludCBpbmRleCwgZG91YmxlIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZERvdWJsZUlzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZERvdWJsZV8uc2V0RG91YmxlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcGFja2VkX2RvdWJsZSA9IDEwMSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHBhY2tlZERvdWJsZSB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZERvdWJsZShkb3VibGUgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkRG91YmxlSXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkRG91YmxlXy5hZGREb3VibGUodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZG91YmxlIHBhY2tlZF9kb3VibGUgPSAxMDEgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkRG91YmxlIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkRG91YmxlKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBqYXZhLmxhbmcuRG91YmxlPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWREb3VibGVJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcGFja2VkRG91YmxlXyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBkb3VibGUgcGFja2VkX2RvdWJsZSA9IDEwMSBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclBhY2tlZERvdWJsZSgpIHsKICAgICAgICBwYWNrZWREb3VibGVfID0gZW1wdHlEb3VibGVMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDA4MDApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuQm9vbGVhbkxpc3QgcGFja2VkQm9vbF8gPSBlbXB0eUJvb2xlYW5MaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRCb29sSXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcGFja2VkQm9vbF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZEJvb2xfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZEJvb2xfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVQYWNrZWRCb29sSXNNdXRhYmxlKGludCBjYXBhY2l0eSkgewogICAgICAgIGlmICghcGFja2VkQm9vbF8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZEJvb2xfID0gbWFrZU11dGFibGVDb3B5KHBhY2tlZEJvb2xfLCBjYXBhY2l0eSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCBwYWNrZWRfYm9vbCA9IDEwMiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRCb29sLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgICAgZ2V0UGFja2VkQm9vbExpc3QoKSB7CiAgICAgICAgcGFja2VkQm9vbF8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRCb29sXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCBwYWNrZWRfYm9vbCA9IDEwMiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRCb29sLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRCb29sQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEJvb2xfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCBwYWNrZWRfYm9vbCA9IDEwMiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkQm9vbCBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBnZXRQYWNrZWRCb29sKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRCb29sXy5nZXRCb29sZWFuKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgYm9vbCBwYWNrZWRfYm9vbCA9IDEwMiBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcGFja2VkQm9vbCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZEJvb2woCiAgICAgICAgICBpbnQgaW5kZXgsIGJvb2xlYW4gdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkQm9vbElzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEJvb2xfLnNldEJvb2xlYW4oaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRCb29sIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkQm9vbChib29sZWFuIHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVBhY2tlZEJvb2xJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRCb29sXy5hZGRCb29sZWFuKHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcGFja2VkQm9vbCB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFBhY2tlZEJvb2woCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5Cb29sZWFuPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRCb29sSXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHBhY2tlZEJvb2xfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGJvb2wgcGFja2VkX2Jvb2wgPSAxMDIgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRCb29sKCkgewogICAgICAgIHBhY2tlZEJvb2xfID0gZW1wdHlCb29sZWFuTGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAxMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gcGFja2VkRW51bV8gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVBhY2tlZEVudW1Jc011dGFibGUoKSB7CiAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAyMDAwKSAhPSAwKSkgewogICAgICAgICAgcGFja2VkRW51bV8gPSBuZXcgamF2YS51dGlsLkFycmF5TGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4ocGFja2VkRW51bV8pOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRFbnVtLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZT4gZ2V0UGFja2VkRW51bUxpc3QoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkxpc3RBZGFwdGVyPAogICAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPihwYWNrZWRFbnVtXywgcGFja2VkRW51bV9jb252ZXJ0ZXJfKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRFbnVtLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRQYWNrZWRFbnVtQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEVudW1fLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBwYWNrZWRfZW51bSA9IDEwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcGFja2VkRW51bSBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldFBhY2tlZEVudW0oaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHBhY2tlZEVudW1fY29udmVydGVyXy5jb252ZXJ0KHBhY2tlZEVudW1fLmdldChpbmRleCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHBhY2tlZF9lbnVtID0gMTAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRFbnVtIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGFja2VkRW51bSgKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBlbnN1cmVQYWNrZWRFbnVtSXNNdXRhYmxlKCk7CiAgICAgICAgcGFja2VkRW51bV8uc2V0KGluZGV4LCB2YWx1ZS5nZXROdW1iZXIoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRFbnVtIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUGFja2VkRW51bShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGVuc3VyZVBhY2tlZEVudW1Jc011dGFibGUoKTsKICAgICAgICBwYWNrZWRFbnVtXy5hZGQodmFsdWUuZ2V0TnVtYmVyKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIHBhY2tlZF9lbnVtID0gMTAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZEVudW0gdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxQYWNrZWRFbnVtKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVBhY2tlZEVudW1Jc011dGFibGUoKTsKICAgICAgICBmb3IgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZSB2YWx1ZSA6IHZhbHVlcykgewogICAgICAgICAgcGFja2VkRW51bV8uYWRkKHZhbHVlLmdldE51bWJlcigpKTsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgcGFja2VkX2VudW0gPSAxMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJQYWNrZWRFbnVtKCkgewogICAgICAgIHBhY2tlZEVudW1fID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAyMDAwKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkVHlwZXNMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkVHlwZXNMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkVHlwZXNMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdFBhY2tlZFR5cGVzTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0UGFja2VkVHlwZXNMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdFBhY2tlZFR5cGVzTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RQYWNrZWRUeXBlc0xpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdFBhY2tlZFR5cGVzTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZFR5cGVzTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RBbGxFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLgogICAgICAgICAgRXh0ZW5kYWJsZU1lc3NhZ2VPckJ1aWxkZXI8VGVzdEFsbEV4dGVuc2lvbnNMaXRlPiB7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RBbGxFeHRlbnNpb25zTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVNZXNzYWdlPAogICAgICAgIFRlc3RBbGxFeHRlbnNpb25zTGl0ZT4gaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSkKICAgICAgVGVzdEFsbEV4dGVuc2lvbnNMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0QWxsRXh0ZW5zaW9uc0xpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdEFsbEV4dGVuc2lvbnNMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwgPz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdEFsbEV4dGVuc2lvbnNMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RBbGxFeHRlbnNpb25zTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuRXh0ZW5kYWJsZU1lc3NhZ2U8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlPi5FeHRlbnNpb25Xcml0ZXIKICAgICAgICAgIGV4dGVuc2lvbldyaXRlciA9IG5ld0V4dGVuc2lvbldyaXRlcigpOwogICAgICBleHRlbnNpb25Xcml0ZXIud3JpdGVVbnRpbCg1MzY4NzA5MTIsIG91dHB1dCk7CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBzaXplICs9IGV4dGVuc2lvbnNTZXJpYWxpemVkU2l6ZSgpOwogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpIG9iajsKCiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0RXh0ZW5zaW9uRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldEV4dGVuc2lvbkZpZWxkcygpKSkKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaGFzaCA9IGhhc2hGaWVsZHMoaGFzaCwgZ2V0RXh0ZW5zaW9uRmllbGRzKCkpOwogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLCBCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxFeHRlbnNpb25zTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUodGhpcyk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwgVHlwZT4gZXh0ZW5zaW9uLAogICAgICAgICAgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRFeHRlbnNpb24oZXh0ZW5zaW9uLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgc2V0RXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsIGphdmEudXRpbC5MaXN0PFR5cGU+PiBleHRlbnNpb24sCiAgICAgICAgICBpbnQgaW5kZXgsIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RXh0ZW5zaW9uKGV4dGVuc2lvbiwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBhZGRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkRXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUPiBCdWlsZGVyIGNsZWFyRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsIFQ+IGV4dGVuc2lvbikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckV4dGVuc2lvbihleHRlbnNpb24pOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIHRoaXMubWVyZ2VFeHRlbnNpb25GaWVsZHMob3RoZXIpOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBpZiAoIWV4dGVuc2lvbnNBcmVJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0QWxsRXh0ZW5zaW9uc0xpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdEFsbEV4dGVuc2lvbnNMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEFsbEV4dGVuc2lvbnNMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RBbGxFeHRlbnNpb25zTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzQSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYS4KICAgICAqLwogICAgaW50IGdldEEoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIE9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSkKICAgICAgT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBPcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBPcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X09wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEFfRklFTERfTlVNQkVSID0gMTc7CiAgICBwcml2YXRlIGludCBhXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgIHJldHVybiBhXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDE3LCBhXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMTcsIGFfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpIG9iajsKCiAgICAgIGlmIChoYXNBKCkgIT0gb3RoZXIuaGFzQSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICBpZiAoZ2V0QSgpCiAgICAgICAgICAgICE9IG90aGVyLmdldEEoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0EoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEFfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEEoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0Lk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X09wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X09wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGFfID0gMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X09wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuYV8gPSBhXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzQSgpKSB7CiAgICAgICAgICBzZXRBKG90aGVyLmdldEEoKSk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTM2OiB7CiAgICAgICAgICAgICAgICBhXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEzNgogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGludCBhXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gMTc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRBKCkgewogICAgICAgIHJldHVybiBhXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDE3OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBhIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0QShpbnQgdmFsdWUpIHsKCiAgICAgICAgYV8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSAxNzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgYV8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0Lk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0Lk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxPcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPE9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBPcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxPcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzQSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYS4KICAgICAqLwogICAgaW50IGdldEEoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSkKICAgICAgUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBSZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBSZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEFfRklFTERfTlVNQkVSID0gNDc7CiAgICBwcml2YXRlIGludCBhXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEEoKSB7CiAgICAgIHJldHVybiBhXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDQ3LCBhXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoNDcsIGFfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpIG9iajsKCiAgICAgIGlmIChoYXNBKCkgIT0gb3RoZXIuaGFzQSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICBpZiAoZ2V0QSgpCiAgICAgICAgICAgICE9IG90aGVyLmdldEEoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0EoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEFfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEEoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGFfID0gMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuYV8gPSBhXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzQSgpKSB7CiAgICAgICAgICBzZXRBKG90aGVyLmdldEEoKSk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMzc2OiB7CiAgICAgICAgICAgICAgICBhXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM3NgogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGludCBhXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBhID0gNDc7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGEgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNBKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRBKCkgewogICAgICAgIHJldHVybiBhXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYSA9IDQ3OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBhIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0QShpbnQgdmFsdWUpIHsKCiAgICAgICAgYV8gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGEgPSA0Nzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgYV8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBSZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuCiAgICAgICAgICBFeHRlbmRhYmxlTWVzc2FnZU9yQnVpbGRlcjxUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGU+IHsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZU1lc3NhZ2U8CiAgICAgICAgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlPiBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKQogICAgICBUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLCA/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBpZiAoIWV4dGVuc2lvbnNBcmVJbml0aWFsaXplZCgpKSB7CiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5FeHRlbmRhYmxlTWVzc2FnZTxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGU+LkV4dGVuc2lvbldyaXRlcgogICAgICAgICAgZXh0ZW5zaW9uV3JpdGVyID0gbmV3RXh0ZW5zaW9uV3JpdGVyKCk7CiAgICAgIGV4dGVuc2lvbldyaXRlci53cml0ZVVudGlsKDUzNjg3MDkxMiwgb3V0cHV0KTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHNpemUgKz0gZXh0ZW5zaW9uc1NlcmlhbGl6ZWRTaXplKCk7CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRFeHRlbnNpb25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0RXh0ZW5zaW9uRmllbGRzKCkpKQogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBoYXNoID0gaGFzaEZpZWxkcyhoYXNoLCBnZXRFeHRlbnNpb25GaWVsZHMoKSk7CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsIEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSh0aGlzKTsKICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIHNldEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLCBUeXBlPiBleHRlbnNpb24sCiAgICAgICAgICBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIGludCBpbmRleCwgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRFeHRlbnNpb24oZXh0ZW5zaW9uLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIGFkZEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRFeHRlbnNpb24oZXh0ZW5zaW9uLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFQ+IEJ1aWxkZXIgY2xlYXJFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwgVD4gZXh0ZW5zaW9uKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRXh0ZW5zaW9uKGV4dGVuc2lvbik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgdGhpcy5tZXJnZUV4dGVuc2lvbkZpZWxkcyhvdGhlcik7CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGlmICghZXh0ZW5zaW9uc0FyZUluaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSkKICAgICAgVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKSBvYmo7CgogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3ROZXN0ZWRFeHRlbnNpb25MaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKHRoaXMpOwogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE5lc3RlZEV4dGVuc2lvbkxpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE5lc3RlZEV4dGVuc2lvbkxpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE5FU1RFRF9FWFRFTlNJT05fRklFTERfTlVNQkVSID0gMTIzNDU7CiAgICAvKioKICAgICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgICAgamF2YS5sYW5nLkludGVnZXI+IG5lc3RlZEV4dGVuc2lvbiA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgICAubmV3TWVzc2FnZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3ROZXN0ZWRFeHRlbnNpb25MaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpLAogICAgICAgICAgMCwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgICAgbnVsbCk7CiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3REZXByZWNhdGVkTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkIGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ0CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlcHJlY2F0ZWRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkIGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ0CiAgICAgKiBAcmV0dXJuIFRoZSBkZXByZWNhdGVkRmllbGQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBpbnQgZ2V0RGVwcmVjYXRlZEZpZWxkKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkMiA9IDIgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDIgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDUKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDIoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgZGVwcmVjYXRlZF9maWVsZDIgPSAyIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQyIGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ1CiAgICAgKiBAcmV0dXJuIFRoZSBkZXByZWNhdGVkRmllbGQyLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgaW50IGdldERlcHJlY2F0ZWRGaWVsZDIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZXByZWNhdGVkX2ZpZWxkMyA9IDMgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDMgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDYKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkMyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDMoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlcHJlY2F0ZWRfZmllbGQzID0gMyBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkMyBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NgogICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkMy4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGphdmEubGFuZy5TdHJpbmcgZ2V0RGVwcmVjYXRlZEZpZWxkMygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQzIGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ2CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVwcmVjYXRlZEZpZWxkMy4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldERlcHJlY2F0ZWRGaWVsZDNCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDQgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDcKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkNCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDQgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDcKICAgICAqIEByZXR1cm4gVGhlIGRlcHJlY2F0ZWRGaWVsZDQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgZ2V0RGVwcmVjYXRlZEZpZWxkNCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZU9yQnVpbGRlciBnZXREZXByZWNhdGVkRmllbGQ0T3JCdWlsZGVyKCk7CiAgfQogIC8qKgogICAqIDxwcmU+CiAgICogVGVzdCB0aGF0IGRlcHJlY2F0ZWQgZmllbGRzIHdvcmsuICBXZSBvbmx5IHZlcmlmeSB0aGF0IHRoZXkgY29tcGlsZSAoYXQgb25lCiAgICogcG9pbnQgdGhpcyBmYWlsZWQpLgogICAqIDwvcHJlPgogICAqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdERlcHJlY2F0ZWRMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSkKICAgICAgVGVzdERlcHJlY2F0ZWRMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0RGVwcmVjYXRlZExpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdERlcHJlY2F0ZWRMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdERlcHJlY2F0ZWRMaXRlKCkgewogICAgICBkZXByZWNhdGVkRmllbGQzXyA9ICIiOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3REZXByZWNhdGVkTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdERlcHJlY2F0ZWRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFUFJFQ0FURURfRklFTERfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgaW50IGRlcHJlY2F0ZWRGaWVsZF8gPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkIGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ0CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlcHJlY2F0ZWRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVwcmVjYXRlZF9maWVsZCA9IDEgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZCBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NAogICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGludCBnZXREZXByZWNhdGVkRmllbGQoKSB7CiAgICAgIHJldHVybiBkZXByZWNhdGVkRmllbGRfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFUFJFQ0FURURfRklFTEQyX0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIGludCBkZXByZWNhdGVkRmllbGQyXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGRlcHJlY2F0ZWRfZmllbGQyID0gMiBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkMiBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NQogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDIoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgZGVwcmVjYXRlZF9maWVsZDIgPSAyIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQyIGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ1CiAgICAgKiBAcmV0dXJuIFRoZSBkZXByZWNhdGVkRmllbGQyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGludCBnZXREZXByZWNhdGVkRmllbGQyKCkgewogICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkMl87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVQUkVDQVRFRF9GSUVMRDNfRklFTERfTlVNQkVSID0gMzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSB2b2xhdGlsZSBqYXZhLmxhbmcuT2JqZWN0IGRlcHJlY2F0ZWRGaWVsZDNfID0gIiI7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZXByZWNhdGVkX2ZpZWxkMyA9IDMgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDMgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDYKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkMyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQzKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBkZXByZWNhdGVkX2ZpZWxkMyA9IDMgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDMgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDYKICAgICAqIEByZXR1cm4gVGhlIGRlcHJlY2F0ZWRGaWVsZDMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXREZXByZWNhdGVkRmllbGQzKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlcHJlY2F0ZWRGaWVsZDNfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDNfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlcHJlY2F0ZWRfZmllbGQzID0gMyBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBkZXByZWNhdGVkIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkMyBpcyBkZXByZWNhdGVkLgogICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIGRlcHJlY2F0ZWRGaWVsZDMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0RGVwcmVjYXRlZEZpZWxkM0J5dGVzKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9IGRlcHJlY2F0ZWRGaWVsZDNfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IGI7CiAgICAgICAgcmV0dXJuIGI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFUFJFQ0FURURfRklFTEQ0X0ZJRUxEX05VTUJFUiA9IDQ7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkRmllbGQ0XzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDQgaXMgZGVwcmVjYXRlZC4KICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDcKICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZGVwcmVjYXRlZEZpZWxkNCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQ0KCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZF9maWVsZDQgPSA0IFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQ0IGlzIGRlcHJlY2F0ZWQuCiAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ3CiAgICAgKiBAcmV0dXJuIFRoZSBkZXByZWNhdGVkRmllbGQ0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBnZXREZXByZWNhdGVkRmllbGQ0KCkgewogICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkNF8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGRlcHJlY2F0ZWRGaWVsZDRfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGVPckJ1aWxkZXIgZ2V0RGVwcmVjYXRlZEZpZWxkNE9yQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIGRlcHJlY2F0ZWRGaWVsZDRfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBkZXByZWNhdGVkRmllbGQ0XzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBpZiAoIWhhc0RlcHJlY2F0ZWRGaWVsZDIoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQ0KCkpIHsKICAgICAgICBpZiAoIWdldERlcHJlY2F0ZWRGaWVsZDQoKS5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMSwgZGVwcmVjYXRlZEZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMiwgZGVwcmVjYXRlZEZpZWxkMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgMywgZGVwcmVjYXRlZEZpZWxkM18pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoNCwgZ2V0RGVwcmVjYXRlZEZpZWxkNCgpKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBkZXByZWNhdGVkRmllbGRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDIsIGRlcHJlY2F0ZWRGaWVsZDJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmNvbXB1dGVTdHJpbmdTaXplKDMsIGRlcHJlY2F0ZWRGaWVsZDNfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNCwgZ2V0RGVwcmVjYXRlZEZpZWxkNCgpKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUpIG9iajsKCiAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQoKSAhPSBvdGhlci5oYXNEZXByZWNhdGVkRmllbGQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVwcmVjYXRlZEZpZWxkKCkpIHsKICAgICAgICBpZiAoZ2V0RGVwcmVjYXRlZEZpZWxkKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0RGVwcmVjYXRlZEZpZWxkKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVwcmVjYXRlZEZpZWxkMigpICE9IG90aGVyLmhhc0RlcHJlY2F0ZWRGaWVsZDIoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVwcmVjYXRlZEZpZWxkMigpKSB7CiAgICAgICAgaWYgKGdldERlcHJlY2F0ZWRGaWVsZDIoKQogICAgICAgICAgICAhPSBvdGhlci5nZXREZXByZWNhdGVkRmllbGQyKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRGVwcmVjYXRlZEZpZWxkMygpICE9IG90aGVyLmhhc0RlcHJlY2F0ZWRGaWVsZDMoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzRGVwcmVjYXRlZEZpZWxkMygpKSB7CiAgICAgICAgaWYgKCFnZXREZXByZWNhdGVkRmllbGQzKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXREZXByZWNhdGVkRmllbGQzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDQoKSAhPSBvdGhlci5oYXNEZXByZWNhdGVkRmllbGQ0KCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDQoKSkgewogICAgICAgIGlmICghZ2V0RGVwcmVjYXRlZEZpZWxkNCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RGVwcmVjYXRlZEZpZWxkNCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVQUkVDQVRFRF9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RGVwcmVjYXRlZEZpZWxkKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDIoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFUFJFQ0FURURfRklFTEQyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZXByZWNhdGVkRmllbGQyKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0RlcHJlY2F0ZWRGaWVsZDMoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIERFUFJFQ0FURURfRklFTEQzX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXREZXByZWNhdGVkRmllbGQzKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzRGVwcmVjYXRlZEZpZWxkNCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgREVQUkVDQVRFRF9GSUVMRDRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldERlcHJlY2F0ZWRGaWVsZDQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogVGVzdCB0aGF0IGRlcHJlY2F0ZWQgZmllbGRzIHdvcmsuICBXZSBvbmx5IHZlcmlmeSB0aGF0IHRoZXkgY29tcGlsZSAoYXQgb25lCiAgICAgKiBwb2ludCB0aGlzIGZhaWxlZCkuCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3REZXByZWNhdGVkTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewogICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwogICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpIHsKICAgICAgICBpZiAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICBnZXREZXByZWNhdGVkRmllbGQ0RmllbGRCdWlsZGVyKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBkZXByZWNhdGVkRmllbGRfID0gMDsKICAgICAgICBkZXByZWNhdGVkRmllbGQyXyA9IDA7CiAgICAgICAgZGVwcmVjYXRlZEZpZWxkM18gPSAiIjsKICAgICAgICBkZXByZWNhdGVkRmllbGQ0XyA9IG51bGw7CiAgICAgICAgaWYgKGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlcHJlY2F0ZWRGaWVsZF8gPSBkZXByZWNhdGVkRmllbGRfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmRlcHJlY2F0ZWRGaWVsZDJfID0gZGVwcmVjYXRlZEZpZWxkMl87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZGVwcmVjYXRlZEZpZWxkM18gPSBkZXByZWNhdGVkRmllbGQzXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5kZXByZWNhdGVkRmllbGQ0XyA9IGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgPyBkZXByZWNhdGVkRmllbGQ0XwogICAgICAgICAgICAgIDogZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzRGVwcmVjYXRlZEZpZWxkKCkpIHsKICAgICAgICAgIHNldERlcHJlY2F0ZWRGaWVsZChvdGhlci5nZXREZXByZWNhdGVkRmllbGQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNEZXByZWNhdGVkRmllbGQyKCkpIHsKICAgICAgICAgIHNldERlcHJlY2F0ZWRGaWVsZDIob3RoZXIuZ2V0RGVwcmVjYXRlZEZpZWxkMigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0RlcHJlY2F0ZWRGaWVsZDMoKSkgewogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkM18gPSBvdGhlci5kZXByZWNhdGVkRmllbGQzXzsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRGVwcmVjYXRlZEZpZWxkNCgpKSB7CiAgICAgICAgICBtZXJnZURlcHJlY2F0ZWRGaWVsZDQob3RoZXIuZ2V0RGVwcmVjYXRlZEZpZWxkNCgpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGlmICghaGFzRGVwcmVjYXRlZEZpZWxkMigpKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmIChoYXNEZXByZWNhdGVkRmllbGQ0KCkpIHsKICAgICAgICAgIGlmICghZ2V0RGVwcmVjYXRlZEZpZWxkNCgpLmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICBkZXByZWNhdGVkRmllbGRfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGNhc2UgMTY6IHsKICAgICAgICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDJfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYKICAgICAgICAgICAgICBjYXNlIDI2OiB7CiAgICAgICAgICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI2CiAgICAgICAgICAgICAgY2FzZSAzNDogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0RGVwcmVjYXRlZEZpZWxkNEZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMzQKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBpbnQgZGVwcmVjYXRlZEZpZWxkXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQgaXMgZGVwcmVjYXRlZC4KICAgICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NAogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGRlcHJlY2F0ZWRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkID0gMSBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQgaXMgZGVwcmVjYXRlZC4KICAgICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NAogICAgICAgKiBAcmV0dXJuIFRoZSBkZXByZWNhdGVkRmllbGQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgaW50IGdldERlcHJlY2F0ZWRGaWVsZCgpIHsKICAgICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVwcmVjYXRlZF9maWVsZCA9IDEgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVwcmVjYXRlZEZpZWxkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBCdWlsZGVyIHNldERlcHJlY2F0ZWRGaWVsZChpbnQgdmFsdWUpIHsKCiAgICAgICAgZGVwcmVjYXRlZEZpZWxkXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZGVwcmVjYXRlZF9maWVsZCA9IDEgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgQnVpbGRlciBjbGVhckRlcHJlY2F0ZWRGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgZGVwcmVjYXRlZEZpZWxkXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGRlcHJlY2F0ZWRGaWVsZDJfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGRlcHJlY2F0ZWRfZmllbGQyID0gMiBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQyIGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDUKICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBib29sZWFuIGhhc0RlcHJlY2F0ZWRGaWVsZDIoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkMiA9IDIgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBkZXByZWNhdGVkIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkMiBpcyBkZXByZWNhdGVkLgogICAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ1CiAgICAgICAqIEByZXR1cm4gVGhlIGRlcHJlY2F0ZWRGaWVsZDIuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgaW50IGdldERlcHJlY2F0ZWRGaWVsZDIoKSB7CiAgICAgICAgcmV0dXJuIGRlcHJlY2F0ZWRGaWVsZDJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBkZXByZWNhdGVkX2ZpZWxkMiA9IDIgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZGVwcmVjYXRlZEZpZWxkMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgQnVpbGRlciBzZXREZXByZWNhdGVkRmllbGQyKGludCB2YWx1ZSkgewoKICAgICAgICBkZXByZWNhdGVkRmllbGQyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgZGVwcmVjYXRlZF9maWVsZDIgPSAyIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgY2xlYXJEZXByZWNhdGVkRmllbGQyKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICBkZXByZWNhdGVkRmllbGQyXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBkZXByZWNhdGVkRmllbGQzXyA9ICIiOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlcHJlY2F0ZWRfZmllbGQzID0gMyBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQzIGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDYKICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQzKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlcHJlY2F0ZWRfZmllbGQzID0gMyBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQzIGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDYKICAgICAgICogQHJldHVybiBUaGUgZGVwcmVjYXRlZEZpZWxkMy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXREZXByZWNhdGVkRmllbGQzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gZGVwcmVjYXRlZEZpZWxkM187CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICBkZXByZWNhdGVkRmllbGQzXyA9IHM7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAZGVwcmVjYXRlZCBwcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUuZGVwcmVjYXRlZF9maWVsZDMgaXMgZGVwcmVjYXRlZC4KICAgICAgICogICAgIFNlZSBnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90bztsPTM0NgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3IgZGVwcmVjYXRlZEZpZWxkMy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgICBnZXREZXByZWNhdGVkRmllbGQzQnl0ZXMoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBkZXByZWNhdGVkRmllbGQzXzsKICAgICAgICBpZiAocmVmIGluc3RhbmNlb2YgU3RyaW5nKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkM18gPSBiOwogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGRlcHJlY2F0ZWRGaWVsZDMgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgc2V0RGVwcmVjYXRlZEZpZWxkMygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGRlcHJlY2F0ZWRGaWVsZDNfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgZGVwcmVjYXRlZF9maWVsZDMgPSAzIFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgY2xlYXJEZXByZWNhdGVkRmllbGQzKCkgewogICAgICAgIGRlcHJlY2F0ZWRGaWVsZDNfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0RGVwcmVjYXRlZEZpZWxkMygpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIGRlcHJlY2F0ZWRfZmllbGQzID0gMyBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBieXRlcyBmb3IgZGVwcmVjYXRlZEZpZWxkMyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgQnVpbGRlciBzZXREZXByZWNhdGVkRmllbGQzQnl0ZXMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIGRlcHJlY2F0ZWRGaWVsZDNfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkRmllbGQ0XzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlT3JCdWlsZGVyPiBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQGRlcHJlY2F0ZWQgcHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlLmRlcHJlY2F0ZWRfZmllbGQ0IGlzIGRlcHJlY2F0ZWQuCiAgICAgICAqICAgICBTZWUgZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2xpdGUucHJvdG87bD0zNDcKICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBkZXByZWNhdGVkRmllbGQ0IGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgYm9vbGVhbiBoYXNEZXByZWNhdGVkRmllbGQ0KCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBkZXByZWNhdGVkIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZS5kZXByZWNhdGVkX2ZpZWxkNCBpcyBkZXByZWNhdGVkLgogICAgICAgKiAgICAgU2VlIGdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9saXRlLnByb3RvO2w9MzQ3CiAgICAgICAqIEByZXR1cm4gVGhlIGRlcHJlY2F0ZWRGaWVsZDQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBnZXREZXByZWNhdGVkRmllbGQ0KCkgewogICAgICAgIGlmIChkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGRlcHJlY2F0ZWRGaWVsZDRfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBkZXByZWNhdGVkRmllbGQ0XzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgQnVpbGRlciBzZXREZXByZWNhdGVkRmllbGQ0KGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0XyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgc2V0RGVwcmVjYXRlZEZpZWxkNCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNF8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZF9maWVsZDQgPSA0IFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBCdWlsZGVyIG1lcmdlRGVwcmVjYXRlZEZpZWxkNChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUgdmFsdWUpIHsKICAgICAgICBpZiAoZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSAmJgogICAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0XyAhPSBudWxsICYmCiAgICAgICAgICAgIGRlcHJlY2F0ZWRGaWVsZDRfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXREZXByZWNhdGVkRmllbGQ0QnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0XyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlcHJlY2F0ZWRGaWVsZDRfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSBkZXByZWNhdGVkX2ZpZWxkNCA9IDQgW2RlcHJlY2F0ZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIEJ1aWxkZXIgY2xlYXJEZXByZWNhdGVkRmllbGQ0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICBkZXByZWNhdGVkRmllbGQ0XyA9IG51bGw7CiAgICAgICAgaWYgKGRlcHJlY2F0ZWRGaWVsZDRCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZF9maWVsZDQgPSA0IFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuQnVpbGRlciBnZXREZXByZWNhdGVkRmllbGQ0QnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldERlcHJlY2F0ZWRGaWVsZDRGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0RGVwcmVjYXRlZExpdGUgZGVwcmVjYXRlZF9maWVsZDQgPSA0IFtkZXByZWNhdGVkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGVPckJ1aWxkZXIgZ2V0RGVwcmVjYXRlZEZpZWxkNE9yQnVpbGRlcigpIHsKICAgICAgICBpZiAoZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkNF8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogZGVwcmVjYXRlZEZpZWxkNF87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlIGRlcHJlY2F0ZWRfZmllbGQ0ID0gNCBbZGVwcmVjYXRlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICovCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXREZXByZWNhdGVkRmllbGQ0RmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChkZXByZWNhdGVkRmllbGQ0QnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RGVwcmVjYXRlZExpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgZ2V0RGVwcmVjYXRlZEZpZWxkNCgpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgZGVwcmVjYXRlZEZpZWxkNF8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZGVwcmVjYXRlZEZpZWxkNEJ1aWxkZXJfOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdERlcHJlY2F0ZWRMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdERlcHJlY2F0ZWRMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdERlcHJlY2F0ZWRMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3REZXByZWNhdGVkTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3REZXByZWNhdGVkTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3REZXByZWNhdGVkTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0RGVwcmVjYXRlZExpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3REZXByZWNhdGVkTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RQYXJzaW5nTWVyZ2VMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy4KICAgICAgICAgIEV4dGVuZGFibGVNZXNzYWdlT3JCdWlsZGVyPFRlc3RQYXJzaW5nTWVyZ2VMaXRlPiB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgcmVxdWlyZWRBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzUmVxdWlyZWRBbGxUeXBlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIHJlcXVpcmVkQWxsVHlwZXMuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0UmVxdWlyZWRBbGxUeXBlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRSZXF1aXJlZEFsbFR5cGVzT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxBbGxUeXBlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQWxsVHlwZXMuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T3B0aW9uYWxBbGxUeXBlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbEFsbFR5cGVzT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gCiAgICAgICAgZ2V0UmVwZWF0ZWRBbGxUeXBlc0xpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0UmVwZWF0ZWRBbGxUeXBlcyhpbnQgaW5kZXgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkQWxsVHlwZXNDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgIGdldFJlcGVhdGVkQWxsVHlwZXNPckJ1aWxkZXJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkQWxsVHlwZXNPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbGdyb3VwIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEdyb3VwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxncm91cC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwPiAKICAgICAgICBnZXRSZXBlYXRlZEdyb3VwTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBnZXRSZXBlYXRlZEdyb3VwKGludCBpbmRleCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRHcm91cENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cE9yQnVpbGRlcj4gCiAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cE9yQnVpbGRlckxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRHcm91cE9yQnVpbGRlcigKICAgICAgICBpbnQgaW5kZXgpOwogIH0KICAvKioKICAgKiA8cHJlPgogICAqIFNlZSB0aGUgY29tbWVudHMgb2YgdGhlIHNhbWUgdHlwZSBpbiB1bml0dGVzdC5wcm90by4KICAgKiA8L3ByZT4KICAgKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdFBhcnNpbmdNZXJnZUxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlTWVzc2FnZTwKICAgICAgICBUZXN0UGFyc2luZ01lcmdlTGl0ZT4gaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlKQogICAgICBUZXN0UGFyc2luZ01lcmdlTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdFBhcnNpbmdNZXJnZUxpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdFBhcnNpbmdNZXJnZUxpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUsID8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RQYXJzaW5nTWVyZ2VMaXRlKCkgewogICAgICByZXBlYXRlZEFsbFR5cGVzXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcmVwZWF0ZWRHcm91cF8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdFBhcnNpbmdNZXJnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIGludGVyZmFjZSBSZXBlYXRlZEZpZWxkc0dlbmVyYXRvck9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiAKICAgICAgICAgIGdldEZpZWxkMUxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoaW50IGluZGV4KTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgaW50IGdldEZpZWxkMUNvdW50KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEZpZWxkMU9yQnVpbGRlckxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDFPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gCiAgICAgICAgICBnZXRGaWVsZDJMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RmllbGQyKGludCBpbmRleCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIGludCBnZXRGaWVsZDJDb3VudCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRGaWVsZDJPckJ1aWxkZXJMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQyT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KTsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IAogICAgICAgICAgZ2V0RmllbGQzTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEZpZWxkMyhpbnQgaW5kZXgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBpbnQgZ2V0RmllbGQzQ291bnQoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RmllbGQzT3JCdWlsZGVyTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEZpZWxkM09yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCk7CgogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMT4gCiAgICAgICAgICBnZXRHcm91cDFMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDEgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIGdldEdyb3VwMShpbnQgaW5kZXgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIGludCBnZXRHcm91cDFDb3VudCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDFPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0R3JvdXAxT3JCdWlsZGVyTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMU9yQnVpbGRlciBnZXRHcm91cDFPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDI+IAogICAgICAgICAgZ2V0R3JvdXAyTGlzdCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBnZXRHcm91cDIoaW50IGluZGV4KTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBpbnQgZ2V0R3JvdXAyQ291bnQoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEdyb3VwMk9yQnVpbGRlckxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMiA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDJPckJ1aWxkZXIgZ2V0R3JvdXAyT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KTsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiAKICAgICAgICAgIGdldEV4dDFMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEV4dDEoaW50IGluZGV4KTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIGludCBnZXRFeHQxQ291bnQoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEV4dDFPckJ1aWxkZXJMaXN0KCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEV4dDFPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpOwoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IAogICAgICAgICAgZ2V0RXh0Mkxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RXh0MihpbnQgaW5kZXgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgaW50IGdldEV4dDJDb3VudCgpOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RXh0Mk9yQnVpbGRlckxpc3QoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RXh0Mk9yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCk7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcikKICAgICAgICBSZXBlYXRlZEZpZWxkc0dlbmVyYXRvck9yQnVpbGRlciB7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgICAgLy8gVXNlIFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgIHByaXZhdGUgUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBSZXBlYXRlZEZpZWxkc0dlbmVyYXRvcigpIHsKICAgICAgICBmaWVsZDFfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGZpZWxkMl8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgZmllbGQzXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBncm91cDFfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIGdyb3VwMl8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgZXh0MV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgZXh0Ml8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICAgIHJldHVybiBuZXcgUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwdWJsaWMgaW50ZXJmYWNlIEdyb3VwMU9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxKQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZmllbGQxIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBib29sZWFuIGhhc0ZpZWxkMSgpOwogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDExOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBmaWVsZDEuCiAgICAgICAgICovCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoKTsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDFPckJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBHcm91cDEgZXh0ZW5kcwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEpCiAgICAgICAgICBHcm91cDFPckJ1aWxkZXIgewogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgICAgICAvLyBVc2UgR3JvdXAxLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgICAgcHJpdmF0ZSBHcm91cDEoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBHcm91cDEoKSB7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICAgIHJldHVybiBuZXcgR3JvdXAxKCk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDFfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDFfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBGSUVMRDFfRklFTERfTlVNQkVSID0gMTE7CiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMV87CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZmllbGQxIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzRmllbGQxKCkgewogICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgZmllbGQxLgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoKSB7CiAgICAgICAgICByZXR1cm4gZmllbGQxXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGZpZWxkMV87CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDExOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQxT3JCdWlsZGVyKCkgewogICAgICAgICAgcmV0dXJuIGZpZWxkMV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBmaWVsZDFfOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxMSwgZ2V0RmllbGQxKCkpOwogICAgICAgICAgfQogICAgICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICAgICAgc2l6ZSA9IDA7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMSwgZ2V0RmllbGQxKCkpOwogICAgICAgICAgfQogICAgICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgICAgICByZXR1cm4gc2l6ZTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxKSkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgICAgICB9CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxKSBvYmo7CgogICAgICAgICAgaWYgKGhhc0ZpZWxkMSgpICE9IG90aGVyLmhhc0ZpZWxkMSgpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBpZiAoaGFzRmllbGQxKCkpIHsKICAgICAgICAgICAgaWYgKCFnZXRGaWVsZDEoKQogICAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRGaWVsZDEoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgICAgIH0KICAgICAgICAgIGludCBoYXNoID0gNDE7CiAgICAgICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGlmIChoYXNGaWVsZDEoKSkgewogICAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBGSUVMRDFfRklFTERfTlVNQkVSOwogICAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRGaWVsZDEoKS5oYXNoQ29kZSgpOwogICAgICAgICAgfQogICAgICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgICAgIHJldHVybiBoYXNoOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VGcm9tKAogICAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VGcm9tKAogICAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZUZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIHBhcnNlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VGcm9tKAogICAgICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIHBhcnNlRnJvbSgKICAgICAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcGFyc2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIHByb3RvdHlwZSkgewogICAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMX0KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEpCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMU9yQnVpbGRlciB7CiAgICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAxX2Rlc2NyaXB0b3I7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgICAgfQoKICAgICAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEubmV3QnVpbGRlcigpCiAgICAgICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgICAgIH0KCiAgICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICAgICAgZ2V0RmllbGQxRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgICAgZmllbGQxXyA9IG51bGw7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAxX2Rlc2NyaXB0b3I7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgYnVpbGQoKSB7CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSh0aGlzKTsKICAgICAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICAgICAgb25CdWlsdCgpOwogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgICAgfQoKICAgICAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSByZXN1bHQpIHsKICAgICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgICByZXN1bHQuZmllbGQxXyA9IGZpZWxkMUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICAgICAgPyBmaWVsZDFfCiAgICAgICAgICAgICAgICAgIDogZmllbGQxQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSkgewogICAgICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSlvdGhlcik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgb3RoZXIpIHsKICAgICAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgIGlmIChvdGhlci5oYXNGaWVsZDEoKSkgewogICAgICAgICAgICAgIG1lcmdlRmllbGQxKG90aGVyLmdldEZpZWxkMSgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICBjYXNlIDkwOiB7CiAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgfSAvLyBjYXNlIDkwCiAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMV87CiAgICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiBmaWVsZDFCdWlsZGVyXzsKICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBmaWVsZDEgZmllbGQgaXMgc2V0LgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgYm9vbGVhbiBoYXNGaWVsZDEoKSB7CiAgICAgICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAgICogQHJldHVybiBUaGUgZmllbGQxLgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoKSB7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkMV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBmaWVsZDFfOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTE7PC9jb2RlPgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZDEoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZmllbGQxXyA9IHZhbHVlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkMSgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgZmllbGQxXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRmllbGQxKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkgJiYKICAgICAgICAgICAgICAgIGZpZWxkMV8gIT0gbnVsbCAmJgogICAgICAgICAgICAgICAgZmllbGQxXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgICAgICBnZXRGaWVsZDFCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZmllbGQxXyA9IHZhbHVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChmaWVsZDFfICE9IG51bGwpIHsKICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDExOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZDEoKSB7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgICAgZmllbGQxXyA9IG51bGw7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDExOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRGaWVsZDFCdWlsZGVyKCkgewogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICByZXR1cm4gZ2V0RmllbGQxRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEZpZWxkMU9yQnVpbGRlcigpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgICByZXR1cm4gZmllbGQxQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJldHVybiBmaWVsZDFfID09IG51bGwgPwogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogZmllbGQxXzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICAgIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICBmaWVsZDFCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICAgICAgZ2V0RmllbGQxKCksCiAgICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgICAgICBmaWVsZDFfID0gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmllbGQxQnVpbGRlcl87CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICAgIH0KCgogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxKQogICAgICAgIH0KCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSkKICAgICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgREVGQVVMVF9JTlNUQU5DRTsKICAgICAgICBzdGF0aWMgewogICAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEoKTsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8R3JvdXAxPgogICAgICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxHcm91cDE+KCkgewogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEdyb3VwMSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgICAgIH0KICAgICAgICB9OwoKICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPEdyb3VwMT4gcGFyc2VyKCkgewogICAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8R3JvdXAxPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgICB9CgogICAgICB9CgogICAgICBwdWJsaWMgaW50ZXJmYWNlIEdyb3VwMk9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyKQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZmllbGQxIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBib29sZWFuIGhhc0ZpZWxkMSgpOwogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFRoZSBmaWVsZDEuCiAgICAgICAgICovCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoKTsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDFPckJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBHcm91cDIgZXh0ZW5kcwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIpCiAgICAgICAgICBHcm91cDJPckJ1aWxkZXIgewogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgICAgICAvLyBVc2UgR3JvdXAyLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICAgICAgcHJpdmF0ZSBHcm91cDIoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgICBzdXBlcihidWlsZGVyKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBHcm91cDIoKSB7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgICAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICAgIHJldHVybiBuZXcgR3JvdXAyKCk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDJfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDJfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBGSUVMRDFfRklFTERfTlVNQkVSID0gMjE7CiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMV87CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZmllbGQxIGZpZWxkIGlzIHNldC4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzRmllbGQxKCkgewogICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgZmllbGQxLgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDEoKSB7CiAgICAgICAgICByZXR1cm4gZmllbGQxXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGZpZWxkMV87CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQxT3JCdWlsZGVyKCkgewogICAgICAgICAgcmV0dXJuIGZpZWxkMV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBmaWVsZDFfOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgyMSwgZ2V0RmllbGQxKCkpOwogICAgICAgICAgfQogICAgICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICAgICAgc2l6ZSA9IDA7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyMSwgZ2V0RmllbGQxKCkpOwogICAgICAgICAgfQogICAgICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgICAgICByZXR1cm4gc2l6ZTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyKSkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgICAgICB9CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyKSBvYmo7CgogICAgICAgICAgaWYgKGhhc0ZpZWxkMSgpICE9IG90aGVyLmhhc0ZpZWxkMSgpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBpZiAoaGFzRmllbGQxKCkpIHsKICAgICAgICAgICAgaWYgKCFnZXRGaWVsZDEoKQogICAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRGaWVsZDEoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgICAgIH0KICAgICAgICAgIGludCBoYXNoID0gNDE7CiAgICAgICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGlmIChoYXNGaWVsZDEoKSkgewogICAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBGSUVMRDFfRklFTERfTlVNQkVSOwogICAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRGaWVsZDEoKS5oYXNoQ29kZSgpOwogICAgICAgICAgfQogICAgICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgICAgIHJldHVybiBoYXNoOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VGcm9tKAogICAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VGcm9tKAogICAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZUZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHBhcnNlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VGcm9tKAogICAgICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHBhcnNlRnJvbSgKICAgICAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcGFyc2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgICAgICB9CiAgICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyIHByb3RvdHlwZSkgewogICAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMn0KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIpCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlciB7CiAgICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAyX2Rlc2NyaXB0b3I7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgICAgfQoKICAgICAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIubmV3QnVpbGRlcigpCiAgICAgICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgICAgIH0KCiAgICAgICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICAgICAgZ2V0RmllbGQxRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgICAgZmllbGQxXyA9IG51bGw7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAyX2Rlc2NyaXB0b3I7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgYnVpbGQoKSB7CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgICAgfQoKICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMih0aGlzKTsKICAgICAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICAgICAgb25CdWlsdCgpOwogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgICAgfQoKICAgICAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiByZXN1bHQpIHsKICAgICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgICByZXN1bHQuZmllbGQxXyA9IGZpZWxkMUJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICAgICAgPyBmaWVsZDFfCiAgICAgICAgICAgICAgICAgIDogZmllbGQxQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMikgewogICAgICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMilvdGhlcik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgb3RoZXIpIHsKICAgICAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMi5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgIGlmIChvdGhlci5oYXNGaWVsZDEoKSkgewogICAgICAgICAgICAgIG1lcmdlRmllbGQxKG90aGVyLmdldEZpZWxkMSgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CgogICAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICBjYXNlIDE3MDogewogICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICBnZXRGaWVsZDFGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxNzAKICAgICAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxXzsKICAgICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IGZpZWxkMUJ1aWxkZXJfOwogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGZpZWxkMSBmaWVsZCBpcyBzZXQuCiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBib29sZWFuIGhhc0ZpZWxkMSgpIHsKICAgICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICAgKiBAcmV0dXJuIFRoZSBmaWVsZDEuCiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEZpZWxkMSgpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICByZXR1cm4gZmllbGQxXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGZpZWxkMV87CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkMUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAyMTs8L2NvZGU+CiAgICAgICAgICAgKi8KICAgICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkMShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBmaWVsZDFfID0gdmFsdWU7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQxKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICBmaWVsZDFfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGaWVsZDEoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSAmJgogICAgICAgICAgICAgICAgZmllbGQxXyAhPSBudWxsICYmCiAgICAgICAgICAgICAgICBmaWVsZDFfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgICAgIGdldEZpZWxkMUJ1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmaWVsZDFfID0gdmFsdWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGZpZWxkMV8gIT0gbnVsbCkgewogICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkMSgpIHsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgICBmaWVsZDFfID0gbnVsbDsKICAgICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIC8qKgogICAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMjE7PC9jb2RlPgogICAgICAgICAgICovCiAgICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldEZpZWxkMUJ1aWxkZXIoKSB7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIHJldHVybiBnZXRGaWVsZDFGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQxT3JCdWlsZGVyKCkgewogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkMV8gPT0gbnVsbCA/CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBmaWVsZDFfOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICAvKioKICAgICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDIxOzwvY29kZT4KICAgICAgICAgICAqLwogICAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICAgICAgZ2V0RmllbGQxRmllbGRCdWlsZGVyKCkgewogICAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgICAgICBnZXRGaWVsZDEoKSwKICAgICAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgICAgIGZpZWxkMV8gPSBudWxsOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXzsKICAgICAgICAgIH0KICAgICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICAgIH0KCiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgICAgfQoKCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIpCiAgICAgICAgfQoKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyKQogICAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBERUZBVUxUX0lOU1RBTkNFOwogICAgICAgIHN0YXRpYyB7CiAgICAgICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMigpOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxHcm91cDI+CiAgICAgICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPEdyb3VwMj4oKSB7CiAgICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgICBwdWJsaWMgR3JvdXAyIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICAgICAgfQogICAgICAgIH07CgogICAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8R3JvdXAyPiBwYXJzZXIoKSB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxHcm91cDI+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICAgIH0KCiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZJRUxEMV9GSUVMRF9OVU1CRVIgPSAxOwogICAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBmaWVsZDFfOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRGaWVsZDFMaXN0KCkgewogICAgICAgIHJldHVybiBmaWVsZDFfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEZpZWxkMU9yQnVpbGRlckxpc3QoKSB7CiAgICAgICAgcmV0dXJuIGZpZWxkMV87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEZpZWxkMUNvdW50KCkgewogICAgICAgIHJldHVybiBmaWVsZDFfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEZpZWxkMShpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZmllbGQxXy5nZXQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQxT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGZpZWxkMV8uZ2V0KGluZGV4KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRklFTEQyX0ZJRUxEX05VTUJFUiA9IDI7CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGZpZWxkMl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldEZpZWxkMkxpc3QoKSB7CiAgICAgICAgcmV0dXJuIGZpZWxkMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RmllbGQyT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZmllbGQyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RmllbGQyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGZpZWxkMl8uc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RmllbGQyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBmaWVsZDJfLmdldChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDJPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZmllbGQyXy5nZXQoaW5kZXgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBGSUVMRDNfRklFTERfTlVNQkVSID0gMzsKICAgICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZmllbGQzXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZ2V0RmllbGQzTGlzdCgpIHsKICAgICAgICByZXR1cm4gZmllbGQzXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRGaWVsZDNPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIHJldHVybiBmaWVsZDNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRGaWVsZDNDb3VudCgpIHsKICAgICAgICByZXR1cm4gZmllbGQzXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDMoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGZpZWxkM18uZ2V0KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEZpZWxkM09yQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBmaWVsZDNfLmdldChpbmRleCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEdST1VQMV9GSUVMRF9OVU1CRVIgPSAxMDsKICAgICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxPiBncm91cDFfOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMT4gZ2V0R3JvdXAxTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ3JvdXAxXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDFPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0R3JvdXAxT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZ3JvdXAxXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAxID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRHcm91cDFDb3VudCgpIHsKICAgICAgICByZXR1cm4gZ3JvdXAxXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEgZ2V0R3JvdXAxKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBncm91cDFfLmdldChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIEdyb3VwMSA9IDEwIHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDFPckJ1aWxkZXIgZ2V0R3JvdXAxT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdyb3VwMV8uZ2V0KGluZGV4KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgR1JPVVAyX0ZJRUxEX05VTUJFUiA9IDIwOwogICAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDI+IGdyb3VwMl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyPiBnZXRHcm91cDJMaXN0KCkgewogICAgICAgIHJldHVybiBncm91cDJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRHcm91cDJPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIHJldHVybiBncm91cDJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBHcm91cDIgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEdyb3VwMkNvdW50KCkgewogICAgICAgIHJldHVybiBncm91cDJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiBnZXRHcm91cDIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdyb3VwMl8uZ2V0KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgR3JvdXAyID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlciBnZXRHcm91cDJPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZ3JvdXAyXy5nZXQoaW5kZXgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFWFQxX0ZJRUxEX05VTUJFUiA9IDEwMDA7CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGV4dDFfOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZ2V0RXh0MUxpc3QoKSB7CiAgICAgICAgcmV0dXJuIGV4dDFfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRFeHQxT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICByZXR1cm4gZXh0MV87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRFeHQxQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGV4dDFfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRFeHQxKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBleHQxXy5nZXQoaW5kZXgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEV4dDFPckJ1aWxkZXIoCiAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZXh0MV8uZ2V0KGluZGV4KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRVhUMl9GSUVMRF9OVU1CRVIgPSAxMDAxOwogICAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBleHQyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldEV4dDJMaXN0KCkgewogICAgICAgIHJldHVybiBleHQyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0RXh0Mk9yQnVpbGRlckxpc3QoKSB7CiAgICAgICAgcmV0dXJuIGV4dDJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0RXh0MkNvdW50KCkgewogICAgICAgIHJldHVybiBleHQyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RXh0MihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gZXh0Ml8uZ2V0KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRFeHQyT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGV4dDJfLmdldChpbmRleCk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBmaWVsZDFfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDEsIGZpZWxkMV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBmaWVsZDJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDIsIGZpZWxkMl8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBmaWVsZDNfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDMsIGZpZWxkM18uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBncm91cDFfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVHcm91cCgxMCwgZ3JvdXAxXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGdyb3VwMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIG91dHB1dC53cml0ZUdyb3VwKDIwLCBncm91cDJfLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZXh0MV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMTAwMCwgZXh0MV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBleHQyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxMDAxLCBleHQyXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgICBzaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGZpZWxkMV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEsIGZpZWxkMV8uZ2V0KGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBmaWVsZDJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyLCBmaWVsZDJfLmdldChpKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZmllbGQzXy5zaXplKCk7IGkrKykgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMywgZmllbGQzXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGdyb3VwMV8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUdyb3VwU2l6ZSgxMCwgZ3JvdXAxXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGdyb3VwMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUdyb3VwU2l6ZSgyMCwgZ3JvdXAyXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGV4dDFfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMDAwLCBleHQxXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGV4dDJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMDAxLCBleHQyXy5nZXQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgICAgcmV0dXJuIHNpemU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcikpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgICB9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3Igb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IpIG9iajsKCiAgICAgICAgaWYgKCFnZXRGaWVsZDFMaXN0KCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRGaWVsZDFMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKCFnZXRGaWVsZDJMaXN0KCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRGaWVsZDJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKCFnZXRGaWVsZDNMaXN0KCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRGaWVsZDNMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKCFnZXRHcm91cDFMaXN0KCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRHcm91cDFMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKCFnZXRHcm91cDJMaXN0KCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRHcm91cDJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKCFnZXRFeHQxTGlzdCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0RXh0MUxpc3QoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICBpZiAoIWdldEV4dDJMaXN0KCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRFeHQyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgICB9CiAgICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgICBpZiAoZ2V0RmllbGQxQ291bnQoKSA+IDApIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEZJRUxEMV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRGaWVsZDFMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKGdldEZpZWxkMkNvdW50KCkgPiAwKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBGSUVMRDJfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RmllbGQyTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgICAgfQogICAgICAgIGlmIChnZXRGaWVsZDNDb3VudCgpID4gMCkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgRklFTEQzX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEZpZWxkM0xpc3QoKS5oYXNoQ29kZSgpOwogICAgICAgIH0KICAgICAgICBpZiAoZ2V0R3JvdXAxQ291bnQoKSA+IDApIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEdST1VQMV9GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRHcm91cDFMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKGdldEdyb3VwMkNvdW50KCkgPiAwKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBHUk9VUDJfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0R3JvdXAyTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgICAgfQogICAgICAgIGlmIChnZXRFeHQxQ291bnQoKSA+IDApIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEVYVDFfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0RXh0MUxpc3QoKS5oYXNoQ29kZSgpOwogICAgICAgIH0KICAgICAgICBpZiAoZ2V0RXh0MkNvdW50KCkgPiAwKSB7CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBFWFQyX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEV4dDJMaXN0KCkuaGFzaENvZGUoKTsKICAgICAgICB9CiAgICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgICAgcmV0dXJuIGhhc2g7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VGcm9tKAogICAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcHJvdG90eXBlKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3J9CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKQogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JPckJ1aWxkZXIgewogICAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5CdWlsZGVyLmNsYXNzKTsKICAgICAgICB9CgogICAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5uZXdCdWlsZGVyKCkKICAgICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGZpZWxkMV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDFfID0gbnVsbDsKICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGZpZWxkMl8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDJfID0gbnVsbDsKICAgICAgICAgICAgZmllbGQyQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGZpZWxkM18gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDNfID0gbnVsbDsKICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICAgIGlmIChncm91cDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGdyb3VwMV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBncm91cDFfID0gbnVsbDsKICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGdyb3VwMl8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBncm91cDJfID0gbnVsbDsKICAgICAgICAgICAgZ3JvdXAyQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBleHQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDFfID0gbnVsbDsKICAgICAgICAgICAgZXh0MUJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgICB9CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAyMCk7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZXh0Ml8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQyXyA9IG51bGw7CiAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwNDApOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgYnVpbGQoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKHRoaXMpOwogICAgICAgICAgYnVpbGRQYXJ0aWFsUmVwZWF0ZWRGaWVsZHMocmVzdWx0KTsKICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbFJlcGVhdGVkRmllbGRzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHJlc3VsdCkgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICAgICAgZmllbGQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGZpZWxkMV8pOwogICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXN1bHQuZmllbGQxXyA9IGZpZWxkMV87CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQuZmllbGQxXyA9IGZpZWxkMUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgICAgICBmaWVsZDJfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZmllbGQyXyk7CiAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlc3VsdC5maWVsZDJfID0gZmllbGQyXzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlc3VsdC5maWVsZDJfID0gZmllbGQyQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgICAgIGZpZWxkM18gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChmaWVsZDNfKTsKICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0LmZpZWxkM18gPSBmaWVsZDNfOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVzdWx0LmZpZWxkM18gPSBmaWVsZDNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApKSB7CiAgICAgICAgICAgICAgZ3JvdXAxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGdyb3VwMV8pOwogICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA4KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXN1bHQuZ3JvdXAxXyA9IGdyb3VwMV87CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQuZ3JvdXAxXyA9IGdyb3VwMUJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZ3JvdXAyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICAgICAgICBncm91cDJfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZ3JvdXAyXyk7CiAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlc3VsdC5ncm91cDJfID0gZ3JvdXAyXzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlc3VsdC5ncm91cDJfID0gZ3JvdXAyQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgICAgICBleHQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGV4dDFfKTsKICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAyMCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0LmV4dDFfID0gZXh0MV87CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQuZXh0MV8gPSBleHQxQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICAgICAgICBleHQyXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGV4dDJfKTsKICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0LmV4dDJfID0gZXh0Ml87CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQuZXh0Ml8gPSBleHQyQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHJlc3VsdCkgewogICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcikgewogICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcilvdGhlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZmllbGQxXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBpZiAoZmllbGQxXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGZpZWxkMV8gPSBvdGhlci5maWVsZDFfOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBlbnN1cmVGaWVsZDFJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIGZpZWxkMV8uYWRkQWxsKG90aGVyLmZpZWxkMV8pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCFvdGhlci5maWVsZDFfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICAgIGZpZWxkMV8gPSBvdGhlci5maWVsZDFfOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICAgIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIuZmllbGQxXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoIW90aGVyLmZpZWxkMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGZpZWxkMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBmaWVsZDJfID0gb3RoZXIuZmllbGQyXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZW5zdXJlRmllbGQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBmaWVsZDJfLmFkZEFsbChvdGhlci5maWVsZDJfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZmllbGQyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgICBmaWVsZDJCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgICBmaWVsZDJfID0gb3RoZXIuZmllbGQyXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAyKTsKICAgICAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMgPwogICAgICAgICAgICAgICAgICAgICBnZXRGaWVsZDJGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLmZpZWxkMl8pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKCFvdGhlci5maWVsZDNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChmaWVsZDNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgZmllbGQzXyA9IG90aGVyLmZpZWxkM187CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGVuc3VyZUZpZWxkM0lzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgZmllbGQzXy5hZGRBbGwob3RoZXIuZmllbGQzXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAoIW90aGVyLmZpZWxkM18uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICAgICAgZmllbGQzXyA9IG90aGVyLmZpZWxkM187CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICAgICAgICBmaWVsZDNCdWlsZGVyXyA9IAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgICAgZ2V0RmllbGQzRmllbGRCdWlsZGVyKCkgOiBudWxsOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyhvdGhlci5maWVsZDNfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChncm91cDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZ3JvdXAxXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBpZiAoZ3JvdXAxXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGdyb3VwMV8gPSBvdGhlci5ncm91cDFfOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDgpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBlbnN1cmVHcm91cDFJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIGdyb3VwMV8uYWRkQWxsKG90aGVyLmdyb3VwMV8pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCFvdGhlci5ncm91cDFfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChncm91cDFCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGdyb3VwMUJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgICAgIGdyb3VwMUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICAgIGdyb3VwMV8gPSBvdGhlci5ncm91cDFfOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDgpOwogICAgICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICAgIGdldEdyb3VwMUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZ3JvdXAxQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIuZ3JvdXAxXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZ3JvdXAyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoIW90aGVyLmdyb3VwMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGdyb3VwMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBncm91cDJfID0gb3RoZXIuZ3JvdXAyXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZW5zdXJlR3JvdXAySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBncm91cDJfLmFkZEFsbChvdGhlci5ncm91cDJfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZ3JvdXAyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICBpZiAoZ3JvdXAyQnVpbGRlcl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBncm91cDJCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgICBncm91cDJCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgICBncm91cDJfID0gb3RoZXIuZ3JvdXAyXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMgPwogICAgICAgICAgICAgICAgICAgICBnZXRHcm91cDJGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLmdyb3VwMl8pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZXh0MV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGV4dDFfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgZXh0MV8gPSBvdGhlci5leHQxXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDIwKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZW5zdXJlRXh0MUlzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgZXh0MV8uYWRkQWxsKG90aGVyLmV4dDFfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICghb3RoZXIuZXh0MV8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgICBleHQxQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgICAgICAgZXh0MV8gPSBvdGhlci5leHQxXzsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDIwKTsKICAgICAgICAgICAgICAgIGV4dDFCdWlsZGVyXyA9IAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgICAgZ2V0RXh0MUZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZXh0MUJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLmV4dDFfKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoIW90aGVyLmV4dDJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChleHQyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGV4dDJfID0gb3RoZXIuZXh0Ml87CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGVuc3VyZUV4dDJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIGV4dDJfLmFkZEFsbChvdGhlci5leHQyXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAoIW90aGVyLmV4dDJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBleHQyQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgICAgZXh0MkJ1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICAgIGV4dDJfID0gb3RoZXIuZXh0Ml87CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDA0MCk7CiAgICAgICAgICAgICAgICBleHQyQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuYWx3YXlzVXNlRmllbGRCdWlsZGVycyA/CiAgICAgICAgICAgICAgICAgICAgIGdldEV4dDJGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyhvdGhlci5leHQyXyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDEwOiB7CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgbSA9CiAgICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlBBUlNFUiwKICAgICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgZW5zdXJlRmllbGQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgZmllbGQxXy5hZGQobSk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uYWRkTWVzc2FnZShtKTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxMAogICAgICAgICAgICAgICAgY2FzZSAxODogewogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgIGVuc3VyZUZpZWxkMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICAgIGZpZWxkMl8uYWRkKG0pOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZE1lc3NhZ2UobSk7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGNhc2UgMTgKICAgICAgICAgICAgICAgIGNhc2UgMjY6IHsKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBtID0KICAgICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVGaWVsZDNJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgICBmaWVsZDNfLmFkZChtKTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDI2CiAgICAgICAgICAgICAgICBjYXNlIDgzOiB7CiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMSBtID0KICAgICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRHcm91cCgxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDEuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVHcm91cDFJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgICBncm91cDFfLmFkZChtKTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBncm91cDFCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDgzCiAgICAgICAgICAgICAgICBjYXNlIDE2MzogewogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvci5Hcm91cDIgbSA9CiAgICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLlBBUlNFUiwKICAgICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgZW5zdXJlR3JvdXAySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgZ3JvdXAyXy5hZGQobSk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgZ3JvdXAyQnVpbGRlcl8uYWRkTWVzc2FnZShtKTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjMKICAgICAgICAgICAgICAgIGNhc2UgODAwMjogewogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgICBpZiAoZXh0MUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVFeHQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgZXh0MV8uYWRkKG0pOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDgwMDIKICAgICAgICAgICAgICAgIGNhc2UgODAxMDogewogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5QQVJTRVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgZXh0Ml8uYWRkKG0pOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5hZGRNZXNzYWdlKG0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBjYXNlIDgwMTAKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZmllbGQxXyA9CiAgICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZUZpZWxkMUlzTXV0YWJsZSgpIHsKICAgICAgICAgIGlmICghKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgZmllbGQxXyA9IG5ldyBqYXZhLnV0aWwuQXJyYXlMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+KGZpZWxkMV8pOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gZmllbGQxQnVpbGRlcl87CgogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRGaWVsZDFMaXN0KCkgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGZpZWxkMV8pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMUJ1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBpbnQgZ2V0RmllbGQxQ291bnQoKSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZmllbGQxXy5zaXplKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmllbGQxQnVpbGRlcl8uZ2V0Q291bnQoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RmllbGQxKGludCBpbmRleCkgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMV8uZ2V0KGluZGV4KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRNZXNzYWdlKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQxKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlRmllbGQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMV8uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkMSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDFJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQxXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRmllbGQxKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlRmllbGQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMV8uYWRkKHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5hZGRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRGaWVsZDEoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVGaWVsZDFJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQxXy5hZGQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRmllbGQxKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDFJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQxXy5hZGQoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfLmFkZE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEZpZWxkMSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDFJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQxXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5hZGRNZXNzYWdlKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsRmllbGQxKAogICAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IHZhbHVlcykgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQxSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICAgIHZhbHVlcywgZmllbGQxXyk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkMSgpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGZpZWxkMV8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDFCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZUZpZWxkMShpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMUlzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDFfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQxQnVpbGRlcl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldEZpZWxkMUJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoaW5kZXgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDEgPSAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRGaWVsZDFPckJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgaWYgKGZpZWxkMUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMV8uZ2V0KGluZGV4KTsgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDFCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgIGdldEZpZWxkMU9yQnVpbGRlckxpc3QoKSB7CiAgICAgICAgICBpZiAoZmllbGQxQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZmllbGQxQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChmaWVsZDFfKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQxID0gMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRGaWVsZDFCdWlsZGVyKCkgewogICAgICAgICAgcmV0dXJuIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYWRkRmllbGQxQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0RmllbGQxRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMSA9IDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXI+IAogICAgICAgICAgICAgZ2V0RmllbGQxQnVpbGRlckxpc3QoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0RmllbGQxRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICAgIGdldEZpZWxkMUZpZWxkQnVpbGRlcigpIHsKICAgICAgICAgIGlmIChmaWVsZDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGZpZWxkMUJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgICAgZmllbGQxXywKICAgICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgIGZpZWxkMV8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGZpZWxkMUJ1aWxkZXJfOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBmaWVsZDJfID0KICAgICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICBwcml2YXRlIHZvaWQgZW5zdXJlRmllbGQySXNNdXRhYmxlKCkgewogICAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgICBmaWVsZDJfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4oZmllbGQyXyk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiBmaWVsZDJCdWlsZGVyXzsKCiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldEZpZWxkMkxpc3QoKSB7CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZmllbGQyXyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmllbGQyQnVpbGRlcl8uZ2V0TWVzc2FnZUxpc3QoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGludCBnZXRGaWVsZDJDb3VudCgpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDJfLnNpemUoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDJCdWlsZGVyXy5nZXRDb3VudCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRGaWVsZDIoaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZmllbGQyXy5nZXQoaW5kZXgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMkJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVGaWVsZDJJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQyXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQyKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMklzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDJfLnNldChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRGaWVsZDIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVGaWVsZDJJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQyXy5hZGQodmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEZpZWxkMigKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMklzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDJfLmFkZChpbmRleCwgdmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRGaWVsZDIoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMklzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDJfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQyQnVpbGRlcl8uYWRkTWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRmllbGQyKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkMklzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDJfLmFkZChpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxGaWVsZDIoCiAgICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDJJc011dGFibGUoKTsKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgICAgdmFsdWVzLCBmaWVsZDJfKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyh2YWx1ZXMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQyKCkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZmllbGQyXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkMkJ1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlRmllbGQyKGludCBpbmRleCkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkMl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDJCdWlsZGVyXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgZ2V0RmllbGQyQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0RmllbGQyRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcihpbmRleCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMiA9IDI7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEZpZWxkMk9yQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZmllbGQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZmllbGQyXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkMkJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICAgZ2V0RmllbGQyT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICAgIGlmIChmaWVsZDJCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDJCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KGZpZWxkMl8pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDIgPSAyOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGFkZEZpZWxkMkJ1aWxkZXIoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0RmllbGQyRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRGaWVsZDJCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIHJldHVybiBnZXRGaWVsZDJGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICAgIGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQyID0gMjs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRGaWVsZDJCdWlsZGVyTGlzdCgpIHsKICAgICAgICAgIHJldHVybiBnZXRGaWVsZDJGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyTGlzdCgpOwogICAgICAgIH0KICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgZ2V0RmllbGQyRmllbGRCdWlsZGVyKCkgewogICAgICAgICAgaWYgKGZpZWxkMkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZmllbGQyQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgICBmaWVsZDJfLAogICAgICAgICAgICAgICAgICAgICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApLAogICAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgICAgZmllbGQyXyA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZmllbGQyQnVpbGRlcl87CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGZpZWxkM18gPQogICAgICAgICAgamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVGaWVsZDNJc011dGFibGUoKSB7CiAgICAgICAgICBpZiAoISgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgICAgIGZpZWxkM18gPSBuZXcgamF2YS51dGlsLkFycmF5TGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPihmaWVsZDNfKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IGZpZWxkM0J1aWxkZXJfOwoKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZ2V0RmllbGQzTGlzdCgpIHsKICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChmaWVsZDNfKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDNCdWlsZGVyXy5nZXRNZXNzYWdlTGlzdCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgaW50IGdldEZpZWxkM0NvdW50KCkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkM18uc2l6ZSgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkM0J1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEZpZWxkMyhpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDNfLmdldChpbmRleCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmllbGQzQnVpbGRlcl8uZ2V0TWVzc2FnZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkMygKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUZpZWxkM0lzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDNfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkM0J1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZDMoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQzSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkM18uc2V0KGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEZpZWxkMyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUZpZWxkM0lzTXV0YWJsZSgpOwogICAgICAgICAgICBmaWVsZDNfLmFkZCh2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uYWRkTWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRmllbGQzKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlRmllbGQzSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkM18uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEZpZWxkMygKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQzSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkM18uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWVsZDNCdWlsZGVyXy5hZGRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRGaWVsZDMoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRmllbGQzSXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGZpZWxkM18uYWRkKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbEZpZWxkMygKICAgICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiB2YWx1ZXMpIHsKICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUZpZWxkM0lzTXV0YWJsZSgpOwogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgICAgICB2YWx1ZXMsIGZpZWxkM18pOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkM0J1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKHZhbHVlcyk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZDMoKSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBmaWVsZDNfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZmllbGQzQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVGaWVsZDMoaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZmllbGQzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVGaWVsZDNJc011dGFibGUoKTsKICAgICAgICAgICAgZmllbGQzXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpZWxkM0J1aWxkZXJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRGaWVsZDNCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIHJldHVybiBnZXRGaWVsZDNGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZmllbGQzID0gMzs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RmllbGQzT3JCdWlsZGVyKAogICAgICAgICAgICBpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChmaWVsZDNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZDNfLmdldChpbmRleCk7ICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmllbGQzQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcihpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRGaWVsZDNPckJ1aWxkZXJMaXN0KCkgewogICAgICAgICAgaWYgKGZpZWxkM0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGZpZWxkM0J1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZmllbGQzXyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGZpZWxkMyA9IDM7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYWRkRmllbGQzQnVpbGRlcigpIHsKICAgICAgICAgIHJldHVybiBnZXRGaWVsZDNGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGFkZEZpZWxkM0J1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGdldEZpZWxkM0ZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBmaWVsZDMgPSAzOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyPiAKICAgICAgICAgICAgIGdldEZpZWxkM0J1aWxkZXJMaXN0KCkgewogICAgICAgICAgcmV0dXJuIGdldEZpZWxkM0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXJMaXN0KCk7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+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+IAogICAgICAgICAgICAgZ2V0R3JvdXAyQnVpbGRlckxpc3QoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0R3JvdXAyRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlckxpc3QoKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlcj4gCiAgICAgICAgICAgIGdldEdyb3VwMkZpZWxkQnVpbGRlcigpIHsKICAgICAgICAgIGlmIChncm91cDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGdyb3VwMkJ1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMiwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yLkdyb3VwMk9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgICAgZ3JvdXAyXywKICAgICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgIGdyb3VwMl8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGdyb3VwMkJ1aWxkZXJfOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBleHQxXyA9CiAgICAgICAgICBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZUV4dDFJc011dGFibGUoKSB7CiAgICAgICAgICBpZiAoISgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgICAgIGV4dDFfID0gbmV3IGphdmEudXRpbC5BcnJheUxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4oZXh0MV8pOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gZXh0MUJ1aWxkZXJfOwoKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldEV4dDFMaXN0KCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChleHQxXyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZXh0MUJ1aWxkZXJfLmdldE1lc3NhZ2VMaXN0KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgaW50IGdldEV4dDFDb3VudCgpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZXh0MV8uc2l6ZSgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDFCdWlsZGVyXy5nZXRDb3VudCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0RXh0MShpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZXh0MV8uZ2V0KGluZGV4KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBleHQxQnVpbGRlcl8uZ2V0TWVzc2FnZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRFeHQxKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUV4dDFJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0MV8uc2V0KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MUJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RXh0MSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRXh0MUlzTXV0YWJsZSgpOwogICAgICAgICAgICBleHQxXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQxQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRFeHQxKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUV4dDFJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0MV8uYWRkKHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQxQnVpbGRlcl8uYWRkTWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEV4dDEoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5zdXJlRXh0MUlzTXV0YWJsZSgpOwogICAgICAgICAgICBleHQxXy5hZGQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQxQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRFeHQxKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRXh0MUlzTXV0YWJsZSgpOwogICAgICAgICAgICBleHQxXy5hZGQoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5hZGRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRXh0MSgKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZW5zdXJlRXh0MUlzTXV0YWJsZSgpOwogICAgICAgICAgICBleHQxXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQxQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxFeHQxKAogICAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IHZhbHVlcykgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUV4dDFJc011dGFibGUoKTsKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICAgICAgdmFsdWVzLCBleHQxXyk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MUJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKHZhbHVlcyk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MSA9IDEwMDA7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRXh0MSgpIHsKICAgICAgICAgIGlmIChleHQxQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBleHQxXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMjApOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDFCdWlsZGVyXy5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVFeHQxKGludCBpbmRleCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUV4dDFJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0MV8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQxQnVpbGRlcl8ucmVtb3ZlKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBnZXRFeHQxQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0RXh0MUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoaW5kZXgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0RXh0MU9yQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZXh0MUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDFfLmdldChpbmRleCk7ICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZXh0MUJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgIGdldEV4dDFPckJ1aWxkZXJMaXN0KCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBleHQxQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlckxpc3QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChleHQxXyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDEgPSAxMDAwOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGFkZEV4dDFCdWlsZGVyKCkgewogICAgICAgICAgcmV0dXJuIGdldEV4dDFGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRFeHQxQnVpbGRlcigKICAgICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgICByZXR1cm4gZ2V0RXh0MUZpZWxkQnVpbGRlcigpLmFkZEJ1aWxkZXIoCiAgICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQxID0gMTAwMDs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRFeHQxQnVpbGRlckxpc3QoKSB7CiAgICAgICAgICByZXR1cm4gZ2V0RXh0MUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXJMaXN0KCk7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICBnZXRFeHQxRmllbGRCdWlsZGVyKCkgewogICAgICAgICAgaWYgKGV4dDFCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGV4dDFCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICAgIGV4dDFfLAogICAgICAgICAgICAgICAgICAgICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApLAogICAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgICAgZXh0MV8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGV4dDFCdWlsZGVyXzsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZXh0Ml8gPQogICAgICAgICAgamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVFeHQySXNNdXRhYmxlKCkgewogICAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgICAgICBleHQyXyA9IG5ldyBqYXZhLnV0aWwuQXJyYXlMaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+KGV4dDJfKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IGV4dDJCdWlsZGVyXzsKCiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRFeHQyTGlzdCgpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZXh0Ml8pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDJCdWlsZGVyXy5nZXRNZXNzYWdlTGlzdCgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGludCBnZXRFeHQyQ291bnQoKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDJfLnNpemUoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBleHQyQnVpbGRlcl8uZ2V0Q291bnQoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldEV4dDIoaW50IGluZGV4KSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDJfLmdldChpbmRleCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZXh0MkJ1aWxkZXJfLmdldE1lc3NhZ2UoaW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RXh0MigKICAgICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDJfLnNldChpbmRleCwgdmFsdWUpOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5zZXRNZXNzYWdlKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEV4dDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGV4dDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUV4dDJJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0Ml8uc2V0KGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLnNldE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRXh0Mihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDJfLmFkZCh2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLmFkZE1lc3NhZ2UodmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRFeHQyKAogICAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVuc3VyZUV4dDJJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0Ml8uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkRXh0MigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGV4dDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUV4dDJJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0Ml8uYWRkKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQyQnVpbGRlcl8uYWRkTWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEV4dDIoCiAgICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgICAgaWYgKGV4dDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGVuc3VyZUV4dDJJc011dGFibGUoKTsKICAgICAgICAgICAgZXh0Ml8uYWRkKGluZGV4LCBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsRXh0MigKICAgICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiB2YWx1ZXMpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICAgIHZhbHVlcywgZXh0Ml8pOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dDJCdWlsZGVyXy5hZGRBbGxNZXNzYWdlcyh2YWx1ZXMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIGV4dDIgPSAxMDAxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckV4dDIoKSB7CiAgICAgICAgICBpZiAoZXh0MkJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgZXh0Ml8gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDQwKTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBleHQyQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlRXh0MihpbnQgaW5kZXgpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBlbnN1cmVFeHQySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIGV4dDJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXh0MkJ1aWxkZXJfLnJlbW92ZShpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgZ2V0RXh0MkJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGdldEV4dDJGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldEV4dDJPckJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgaWYgKGV4dDJCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBleHQyXy5nZXQoaW5kZXgpOyAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGV4dDJCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDw/IGV4dGVuZHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICAgICBnZXRFeHQyT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gZXh0MkJ1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXJMaXN0KCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QoZXh0Ml8pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBleHQyID0gMTAwMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRFeHQyQnVpbGRlcigpIHsKICAgICAgICAgIHJldHVybiBnZXRFeHQyRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYWRkRXh0MkJ1aWxkZXIoCiAgICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgICAgcmV0dXJuIGdldEV4dDJGaWVsZEJ1aWxkZXIoKS5hZGRCdWlsZGVyKAogICAgICAgICAgICAgIGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgZXh0MiA9IDEwMDE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXI+IAogICAgICAgICAgICAgZ2V0RXh0MkJ1aWxkZXJMaXN0KCkgewogICAgICAgICAgcmV0dXJuIGdldEV4dDJGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyTGlzdCgpOwogICAgICAgIH0KICAgICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuUmVwZWF0ZWRGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgZ2V0RXh0MkZpZWxkQnVpbGRlcigpIHsKICAgICAgICAgIGlmIChleHQyQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBleHQyQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5SZXBlYXRlZEZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgICBleHQyXywKICAgICAgICAgICAgICAgICAgICAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSwKICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgIGV4dDJfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBleHQyQnVpbGRlcl87CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IpCiAgICAgIH0KCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcikKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgREVGQVVMVF9JTlNUQU5DRTsKICAgICAgc3RhdGljIHsKICAgICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGRzR2VuZXJhdG9yKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEZpZWxkc0dlbmVyYXRvcj4KICAgICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yPigpIHsKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIFJlcGVhdGVkRmllbGRzR2VuZXJhdG9yIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3I+IHBhcnNlcigpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEZpZWxkc0dlbmVyYXRvcj4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEZpZWxkc0dlbmVyYXRvciBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICB9CgogICAgfQoKICAgIHB1YmxpYyBpbnRlcmZhY2UgT3B0aW9uYWxHcm91cE9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxHcm91cEFsbFR5cGVzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsR3JvdXBBbGxUeXBlcy4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc09yQnVpbGRlcigpOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIE9wdGlvbmFsR3JvdXAgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgICAgT3B0aW9uYWxHcm91cE9yQnVpbGRlciB7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgICAgLy8gVXNlIE9wdGlvbmFsR3JvdXAubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgICAgcHJpdmF0ZSBPcHRpb25hbEdyb3VwKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgICB9CiAgICAgIHByaXZhdGUgT3B0aW9uYWxHcm91cCgpIHsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgICAgcmV0dXJuIG5ldyBPcHRpb25hbEdyb3VwKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9HUk9VUF9BTExfVFlQRVNfRklFTERfTlVNQkVSID0gMTE7CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbEdyb3VwQWxsVHlwZXNfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfZ3JvdXBfYWxsX3R5cGVzID0gMTE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsR3JvdXBBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsR3JvdXBBbGxUeXBlcygpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxHcm91cEFsbFR5cGVzLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwQWxsVHlwZXNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc09yQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gb3B0aW9uYWxHcm91cEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBBbGxUeXBlc187CiAgICAgIH0KCiAgICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDExLCBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSk7CiAgICAgICAgfQogICAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICAgIHNpemUgPSAwOwogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTEsIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlcygpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICAgIHJldHVybiBzaXplOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCkpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgICB9CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwKSBvYmo7CgogICAgICAgIGlmIChoYXNPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSAhPSBvdGhlci5oYXNPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChoYXNPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSkgewogICAgICAgICAgaWYgKCFnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKQogICAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgICB9CiAgICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0dST1VQX0FMTF9UWVBFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKS5oYXNoQ29kZSgpOwogICAgICAgIH0KICAgICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgICByZXR1cm4gaGFzaDsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIHByb3RvdHlwZSkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXB9CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyLmNsYXNzKTsKICAgICAgICB9CgogICAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLm5ld0J1aWxkZXIoKQogICAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKICAgICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgIHN1cGVyKHBhcmVudCk7CiAgICAgICAgICBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgdm9pZCBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCkgewogICAgICAgICAgaWYgKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc0ZpZWxkQnVpbGRlcigpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICAgIGlmIChvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgb3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBidWlsZCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCh0aGlzKTsKICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCByZXN1bHQpIHsKICAgICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPSBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgICA/IG9wdGlvbmFsR3JvdXBBbGxUeXBlc18KICAgICAgICAgICAgICAgIDogb3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApIHsKICAgICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cClvdGhlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpIHsKICAgICAgICAgICAgbWVyZ2VPcHRpb25hbEdyb3VwQWxsVHlwZXMob3RoZXIuZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzKCkpOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA5MDogewogICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSA5MAogICAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsR3JvdXBBbGxUeXBlc187CiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfOwogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsR3JvdXBBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cEFsbFR5cGVzKCkgewogICAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxHcm91cEFsbFR5cGVzLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlcygpIHsKICAgICAgICAgIGlmIChvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQWxsVHlwZXNfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxHcm91cEFsbFR5cGVzXzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNfID0gdmFsdWU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcyA9IDExOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICAgIGlmIChvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgICAgfQogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfZ3JvdXBfYWxsX3R5cGVzID0gMTE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxHcm91cEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSAmJgogICAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gIT0gbnVsbCAmJgogICAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPSB2YWx1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChvcHRpb25hbEdyb3VwQWxsVHlwZXNfICE9IG51bGwpIHsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSB7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICAgIGlmIChvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgICAgb3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfZ3JvdXBfYWxsX3R5cGVzID0gMTE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgZ2V0T3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcigpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfZ3JvdXBfYWxsX3R5cGVzID0gMTE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsR3JvdXBBbGxUeXBlc09yQnVpbGRlcigpIHsKICAgICAgICAgIGlmIChvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gb3B0aW9uYWxHcm91cEFsbFR5cGVzXyA9PSBudWxsID8KICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEdyb3VwQWxsVHlwZXNfOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9ncm91cF9hbGxfdHlwZXMgPSAxMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgICBpZiAob3B0aW9uYWxHcm91cEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBvcHRpb25hbEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwQWxsVHlwZXMoKSwKICAgICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBBbGxUeXBlc18gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBBbGxUeXBlc0J1aWxkZXJfOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCgogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgIH0KCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwKQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIHN0YXRpYyB7CiAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwKCk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cCBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE9wdGlvbmFsR3JvdXA+CiAgICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxPcHRpb25hbEdyb3VwPigpIHsKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIE9wdGlvbmFsR3JvdXAgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxPcHRpb25hbEdyb3VwPiBwYXJzZXIoKSB7CiAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cD4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICB9CgogICAgcHVibGljIGludGVyZmFjZSBSZXBlYXRlZEdyb3VwT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSByZXBlYXRlZEdyb3VwQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgYm9vbGVhbiBoYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRHcm91cEFsbFR5cGVzLgogICAgICAgKi8KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICovCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzT3JCdWlsZGVyKCk7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXB9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgUmVwZWF0ZWRHcm91cCBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgICBSZXBlYXRlZEdyb3VwT3JCdWlsZGVyIHsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgICAvLyBVc2UgUmVwZWF0ZWRHcm91cC5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgICBwcml2YXRlIFJlcGVhdGVkR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBSZXBlYXRlZEdyb3VwKCkgewogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICByZXR1cm4gbmV3IFJlcGVhdGVkR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0dST1VQX0FMTF9UWVBFU19GSUVMRF9OVU1CRVIgPSAyMTsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkR3JvdXBBbGxUeXBlc187CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgcmVwZWF0ZWRHcm91cEFsbFR5cGVzIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzUmVwZWF0ZWRHcm91cEFsbFR5cGVzKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEdyb3VwQWxsVHlwZXMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlcGVhdGVkR3JvdXBBbGxUeXBlc187CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzT3JCdWlsZGVyKCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQWxsVHlwZXNfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVwZWF0ZWRHcm91cEFsbFR5cGVzXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMjEsIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygpKTsKICAgICAgICB9CiAgICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgICAgc2l6ZSA9IDA7CiAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyMSwgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzKCkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgICAgcmV0dXJuIHNpemU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICAgIH0KICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXApIG9iajsKCiAgICAgICAgaWYgKGhhc1JlcGVhdGVkR3JvdXBBbGxUeXBlcygpICE9IG90aGVyLmhhc1JlcGVhdGVkR3JvdXBBbGxUeXBlcygpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgaWYgKGhhc1JlcGVhdGVkR3JvdXBBbGxUeXBlcygpKSB7CiAgICAgICAgICBpZiAoIWdldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICAgIH0KICAgICAgICBpbnQgaGFzaCA9IDQxOwogICAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICAgIGlmIChoYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSkgewogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURfR1JPVVBfQUxMX1RZUEVTX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlcygpLmhhc2hDb2RlKCk7CiAgICAgICAgfQogICAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICAgIHJldHVybiBoYXNoOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgcHJvdG90eXBlKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgICByZXR1cm4gYnVpbGRlcjsKICAgICAgfQogICAgICAvKioKICAgICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cH0KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXBPckJ1aWxkZXIgewogICAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkR3JvdXBfZGVzY3JpcHRvcjsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICAgIH0KCiAgICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAubmV3QnVpbGRlcigpCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewogICAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgICBpZiAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAgICAgLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMpIHsKICAgICAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzRmllbGRCdWlsZGVyKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBBbGxUeXBlc18gPSBudWxsOwogICAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIGJ1aWxkKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKHRoaXMpOwogICAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICAgIG9uQnVpbHQoKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwIHJlc3VsdCkgewogICAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgICByZXN1bHQucmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9IHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICAgID8gcmVwZWF0ZWRHcm91cEFsbFR5cGVzXwogICAgICAgICAgICAgICAgOiByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkgewogICAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKW90aGVyKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICAgIGlmIChvdGhlci5oYXNSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSkgewogICAgICAgICAgICBtZXJnZVJlcGVhdGVkR3JvdXBBbGxUeXBlcyhvdGhlci5nZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDE3MDogewogICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAxNzAKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0gLy8gZmluYWxseQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZEdyb3VwQWxsVHlwZXNfOwogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXzsKICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSByZXBlYXRlZEdyb3VwQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBib29sZWFuIGhhc1JlcGVhdGVkR3JvdXBBbGxUeXBlcygpIHsKICAgICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkR3JvdXBBbGxUeXBlcy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXMoKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlcGVhdGVkR3JvdXBBbGxUeXBlc187CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9IHZhbHVlOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMgPSAyMTs8L2NvZGU+CiAgICAgICAgICovCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZVJlcGVhdGVkR3JvdXBBbGxUeXBlcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkgJiYKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNfICE9IG51bGwgJiYKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgICBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNfID0gdmFsdWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEFsbFR5cGVzXyAhPSBudWxsKSB7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRHcm91cEFsbFR5cGVzKCkgewogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzXyA9IG51bGw7CiAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldFJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXIoKSB7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcyA9IDIxOzwvY29kZT4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEdyb3VwQWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBBbGxUeXBlc18gPT0gbnVsbCA/CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVwZWF0ZWRHcm91cEFsbFR5cGVzXzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfZ3JvdXBfYWxsX3R5cGVzID0gMjE7PC9jb2RlPgogICAgICAgICAqLwogICAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzRmllbGRCdWlsZGVyKCkgewogICAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEFsbFR5cGVzQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cEFsbFR5cGVzKCksCiAgICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgICByZXBlYXRlZEdyb3VwQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwQWxsVHlwZXNCdWlsZGVyXzsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgICB9CgoKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwKQogICAgICB9CgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCkKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBERUZBVUxUX0lOU1RBTkNFOwogICAgICBzdGF0aWMgewogICAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZXBlYXRlZEdyb3VwPgogICAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UmVwZWF0ZWRHcm91cD4oKSB7CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBSZXBlYXRlZEdyb3VwIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UmVwZWF0ZWRHcm91cD4gcGFyc2VyKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlcGVhdGVkR3JvdXA+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIFBBUlNFUjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgICB9CgogICAgfQoKICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVFVSVJFRF9BTExfVFlQRVNfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZEFsbFR5cGVzXzsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIHJlcXVpcmVkQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNSZXF1aXJlZEFsbFR5cGVzKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkX2FsbF90eXBlcyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgcmVxdWlyZWRBbGxUeXBlcy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0UmVxdWlyZWRBbGxUeXBlcygpIHsKICAgICAgcmV0dXJuIHJlcXVpcmVkQWxsVHlwZXNfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVxdWlyZWRBbGxUeXBlc187CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkX2FsbF90eXBlcyA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRSZXF1aXJlZEFsbFR5cGVzT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gcmVxdWlyZWRBbGxUeXBlc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiByZXF1aXJlZEFsbFR5cGVzXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9BTExfVFlQRVNfRklFTERfTlVNQkVSID0gMjsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbEFsbFR5cGVzXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEFsbFR5cGVzKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxBbGxUeXBlcy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T3B0aW9uYWxBbGxUeXBlcygpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsQWxsVHlwZXNfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxBbGxUeXBlc187CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbEFsbFR5cGVzT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxBbGxUeXBlc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEFsbFR5cGVzXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9BTExfVFlQRVNfRklFTERfTlVNQkVSID0gMzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiByZXBlYXRlZEFsbFR5cGVzXzsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRSZXBlYXRlZEFsbFR5cGVzTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkQWxsVHlwZXNfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZEFsbFR5cGVzT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkQWxsVHlwZXNfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEFsbFR5cGVzQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEFsbFR5cGVzXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRSZXBlYXRlZEFsbFR5cGVzKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc18uZ2V0KGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldFJlcGVhdGVkQWxsVHlwZXNPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEFsbFR5cGVzXy5nZXQoaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMR1JPVVBfRklFTERfTlVNQkVSID0gMTA7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXAgb3B0aW9uYWxHcm91cF87CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSAxMCB7IC4uLiB9PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbGdyb3VwIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsZ3JvdXAuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwIGdldE9wdGlvbmFsR3JvdXAoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gMTAgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXIgZ2V0T3B0aW9uYWxHcm91cE9yQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxHcm91cF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURHUk9VUF9GSUVMRF9OVU1CRVIgPSAyMDsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwPiByZXBlYXRlZEdyb3VwXzsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwPiBnZXRSZXBlYXRlZEdyb3VwTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyPiAKICAgICAgICBnZXRSZXBlYXRlZEdyb3VwT3JCdWlsZGVyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkR3JvdXBfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBncm91cCBSZXBlYXRlZEdyb3VwID0gMjAgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEdyb3VwQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwXy5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGdyb3VwIFJlcGVhdGVkR3JvdXAgPSAyMCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBnZXRSZXBlYXRlZEdyb3VwKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cF8uZ2V0KGluZGV4KTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZ3JvdXAgUmVwZWF0ZWRHcm91cCA9IDIwIHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyIGdldFJlcGVhdGVkR3JvdXBPckJ1aWxkZXIoCiAgICAgICAgaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEdyb3VwXy5nZXQoaW5kZXgpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmICghaGFzUmVxdWlyZWRBbGxUeXBlcygpKSB7CiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuRXh0ZW5kYWJsZU1lc3NhZ2U8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGU+LkV4dGVuc2lvbldyaXRlcgogICAgICAgICAgZXh0ZW5zaW9uV3JpdGVyID0gbmV3RXh0ZW5zaW9uV3JpdGVyKCk7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMSwgZ2V0UmVxdWlyZWRBbGxUeXBlcygpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDIsIGdldE9wdGlvbmFsQWxsVHlwZXMoKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEFsbFR5cGVzXy5zaXplKCk7IGkrKykgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMywgcmVwZWF0ZWRBbGxUeXBlc18uZ2V0KGkpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVHcm91cCgxMCwgZ2V0T3B0aW9uYWxHcm91cCgpKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkR3JvdXBfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlR3JvdXAoMjAsIHJlcGVhdGVkR3JvdXBfLmdldChpKSk7CiAgICAgIH0KICAgICAgZXh0ZW5zaW9uV3JpdGVyLndyaXRlVW50aWwoNTM2ODcwOTEyLCBvdXRwdXQpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEsIGdldFJlcXVpcmVkQWxsVHlwZXMoKSk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDIsIGdldE9wdGlvbmFsQWxsVHlwZXMoKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEFsbFR5cGVzXy5zaXplKCk7IGkrKykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgzLCByZXBlYXRlZEFsbFR5cGVzXy5nZXQoaSkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVHcm91cFNpemUoMTAsIGdldE9wdGlvbmFsR3JvdXAoKSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEdyb3VwXy5zaXplKCk7IGkrKykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVHcm91cFNpemUoMjAsIHJlcGVhdGVkR3JvdXBfLmdldChpKSk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBleHRlbnNpb25zU2VyaWFsaXplZFNpemUoKTsKICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlKSBvYmo7CgogICAgICBpZiAoaGFzUmVxdWlyZWRBbGxUeXBlcygpICE9IG90aGVyLmhhc1JlcXVpcmVkQWxsVHlwZXMoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzUmVxdWlyZWRBbGxUeXBlcygpKSB7CiAgICAgICAgaWYgKCFnZXRSZXF1aXJlZEFsbFR5cGVzKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXF1aXJlZEFsbFR5cGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQWxsVHlwZXMoKSAhPSBvdGhlci5oYXNPcHRpb25hbEFsbFR5cGVzKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsQWxsVHlwZXMoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxBbGxUeXBlcygpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxBbGxUeXBlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0UmVwZWF0ZWRBbGxUeXBlc0xpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEFsbFR5cGVzTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cCgpICE9IG90aGVyLmhhc09wdGlvbmFsR3JvdXAoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxHcm91cCgpKSB7CiAgICAgICAgaWYgKCFnZXRPcHRpb25hbEdyb3VwKCkKICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPcHRpb25hbEdyb3VwKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFnZXRSZXBlYXRlZEdyb3VwTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkR3JvdXBMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0RXh0ZW5zaW9uRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldEV4dGVuc2lvbkZpZWxkcygpKSkKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc1JlcXVpcmVkQWxsVHlwZXMoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUVVJUkVEX0FMTF9UWVBFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVxdWlyZWRBbGxUeXBlcygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQWxsVHlwZXMoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0FMTF9UWVBFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxBbGxUeXBlcygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGdldFJlcGVhdGVkQWxsVHlwZXNDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0FMTF9UWVBFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRBbGxUeXBlc0xpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEdyb3VwKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTEdST1VQX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPcHRpb25hbEdyb3VwKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoZ2V0UmVwZWF0ZWRHcm91cENvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUkVQRUFURURHUk9VUF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRHcm91cExpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSBoYXNoRmllbGRzKGhhc2gsIGdldEV4dGVuc2lvbkZpZWxkcygpKTsKICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFNlZSB0aGUgY29tbWVudHMgb2YgdGhlIHNhbWUgdHlwZSBpbiB1bml0dGVzdC5wcm90by4KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUsIEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKICAgICAgICBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKICAgICAgICBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCk7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKSB7CiAgICAgICAgaWYgKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgICAgICAuYWx3YXlzVXNlRmllbGRCdWlsZGVycykgewogICAgICAgICAgZ2V0UmVxdWlyZWRBbGxUeXBlc0ZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0T3B0aW9uYWxBbGxUeXBlc0ZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0UmVwZWF0ZWRBbGxUeXBlc0ZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEZpZWxkQnVpbGRlcigpOwogICAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cEZpZWxkQnVpbGRlcigpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgcmVxdWlyZWRBbGxUeXBlc18gPSBudWxsOwogICAgICAgIGlmIChyZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9wdGlvbmFsQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXyA9IG51bGw7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgIG9wdGlvbmFsR3JvdXBfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBfID0gamF2YS51dGlsLkNvbGxlY3Rpb25zLmVtcHR5TGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IG51bGw7CiAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSh0aGlzKTsKICAgICAgICBidWlsZFBhcnRpYWxSZXBlYXRlZEZpZWxkcyhyZXN1bHQpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWxSZXBlYXRlZEZpZWxkcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSByZXN1bHQpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkQWxsVHlwZXNfKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkQWxsVHlwZXNfID0gcmVwZWF0ZWRBbGxUeXBlc187CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEFsbFR5cGVzXyA9IHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IGphdmEudXRpbC5Db2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KHJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMTApOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LnJlcGVhdGVkR3JvdXBfID0gcmVwZWF0ZWRHcm91cF87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEdyb3VwXyA9IHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQucmVxdWlyZWRBbGxUeXBlc18gPSByZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gcmVxdWlyZWRBbGxUeXBlc18KICAgICAgICAgICAgICA6IHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsQWxsVHlwZXNfID0gb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsQWxsVHlwZXNfCiAgICAgICAgICAgICAgOiBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEdyb3VwXyA9IG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgPyBvcHRpb25hbEdyb3VwXwogICAgICAgICAgICAgIDogb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmJ1aWxkKCk7CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLCBUeXBlPiBleHRlbnNpb24sCiAgICAgICAgICBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgaW50IGluZGV4LCBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgYWRkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkRXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUPiBCdWlsZGVyIGNsZWFyRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSwgVD4gZXh0ZW5zaW9uKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRXh0ZW5zaW9uKGV4dGVuc2lvbik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzUmVxdWlyZWRBbGxUeXBlcygpKSB7CiAgICAgICAgICBtZXJnZVJlcXVpcmVkQWxsVHlwZXMob3RoZXIuZ2V0UmVxdWlyZWRBbGxUeXBlcygpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsQWxsVHlwZXMoKSkgewogICAgICAgICAgbWVyZ2VPcHRpb25hbEFsbFR5cGVzKG90aGVyLmdldE9wdGlvbmFsQWxsVHlwZXMoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChyZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEFsbFR5cGVzXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNfID0gb3RoZXIucmVwZWF0ZWRBbGxUeXBlc187CiAgICAgICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDQpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKTsKICAgICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRBbGxUeXBlc18pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoIW90aGVyLnJlcGVhdGVkQWxsVHlwZXNfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID0gbnVsbDsKICAgICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXyA9IG90aGVyLnJlcGVhdGVkQWxsVHlwZXNfOwogICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gPSAKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMgPwogICAgICAgICAgICAgICAgICAgZ2V0UmVwZWF0ZWRBbGxUeXBlc0ZpZWxkQnVpbGRlcigpIDogbnVsbDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXMob3RoZXIucmVwZWF0ZWRBbGxUeXBlc18pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEdyb3VwKCkpIHsKICAgICAgICAgIG1lcmdlT3B0aW9uYWxHcm91cChvdGhlci5nZXRPcHRpb25hbEdyb3VwKCkpOwogICAgICAgIH0KICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRHcm91cF8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIGlmIChyZXBlYXRlZEdyb3VwXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwXyA9IG90aGVyLnJlcGVhdGVkR3JvdXBfOwogICAgICAgICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDEwKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEdyb3VwSXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8uYWRkQWxsKG90aGVyLnJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEdyb3VwXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgaWYgKHJlcGVhdGVkR3JvdXBCdWlsZGVyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBvdGhlci5yZXBlYXRlZEdyb3VwXzsKICAgICAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfID0gCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzID8KICAgICAgICAgICAgICAgICAgIGdldFJlcGVhdGVkR3JvdXBGaWVsZEJ1aWxkZXIoKSA6IG51bGw7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cEJ1aWxkZXJfLmFkZEFsbE1lc3NhZ2VzKG90aGVyLnJlcGVhdGVkR3JvdXBfKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlRXh0ZW5zaW9uRmllbGRzKG90aGVyKTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFoYXNSZXF1aXJlZEFsbFR5cGVzKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTA6IHsKICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIGdldFJlcXVpcmVkQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEwCiAgICAgICAgICAgICAgY2FzZSAxODogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTgKICAgICAgICAgICAgICBjYXNlIDI2OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIG0gPQogICAgICAgICAgICAgICAgICAgIGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLlBBUlNFUiwKICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKTsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18uYWRkKG0pOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmFkZE1lc3NhZ2UobSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjYKICAgICAgICAgICAgICBjYXNlIDgzOiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoMTAsCiAgICAgICAgICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODMKICAgICAgICAgICAgICBjYXNlIDE2MzogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCBtID0KICAgICAgICAgICAgICAgICAgICBpbnB1dC5yZWFkR3JvdXAoMjAsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkR3JvdXAuUEFSU0VSLAogICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRHcm91cElzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwXy5hZGQobSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEdyb3VwQnVpbGRlcl8uYWRkTWVzc2FnZShtKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjMKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkQWxsVHlwZXNfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkX2FsbF90eXBlcyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIHJlcXVpcmVkQWxsVHlwZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzUmVxdWlyZWRBbGxUeXBlcygpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkX2FsbF90eXBlcyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSByZXF1aXJlZEFsbFR5cGVzLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0UmVxdWlyZWRBbGxUeXBlcygpIHsKICAgICAgICBpZiAocmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXF1aXJlZEFsbFR5cGVzXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlcXVpcmVkQWxsVHlwZXNfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcXVpcmVkX2FsbF90eXBlcyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVxdWlyZWRBbGxUeXBlcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICAgIH0KICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNfID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcXVpcmVkQWxsVHlwZXMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXF1aXJlZEFsbFR5cGVzXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZVJlcXVpcmVkQWxsVHlwZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApICYmCiAgICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNfICE9IG51bGwgJiYKICAgICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc18gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRSZXF1aXJlZEFsbFR5cGVzQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXF1aXJlZEFsbFR5cGVzXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJlcXVpcmVkQWxsVHlwZXNfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcXVpcmVkQWxsVHlwZXMoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIHJlcXVpcmVkQWxsVHlwZXNfID0gbnVsbDsKICAgICAgICBpZiAocmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICByZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldFJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gZ2V0UmVxdWlyZWRBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVxdWlyZWRfYWxsX3R5cGVzID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRSZXF1aXJlZEFsbFR5cGVzT3JCdWlsZGVyKCkgewogICAgICAgIGlmIChyZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcXVpcmVkQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXF1aXJlZEFsbFR5cGVzXyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVxdWlyZWRBbGxUeXBlc187CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXF1aXJlZF9hbGxfdHlwZXMgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gCiAgICAgICAgICBnZXRSZXF1aXJlZEFsbFR5cGVzRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChyZXF1aXJlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgZ2V0UmVxdWlyZWRBbGxUeXBlcygpLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgcmVxdWlyZWRBbGxUeXBlc18gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVxdWlyZWRBbGxUeXBlc0J1aWxkZXJfOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxBbGxUeXBlc187CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEFsbFR5cGVzKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQWxsVHlwZXMuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRPcHRpb25hbEFsbFR5cGVzKCkgewogICAgICAgIGlmIChvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsQWxsVHlwZXNfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxBbGxUeXBlc187CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb3B0aW9uYWxfYWxsX3R5cGVzID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc18gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxBbGxUeXBlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxBbGxUeXBlcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkgJiYKICAgICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc18gIT0gbnVsbCAmJgogICAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSB7CiAgICAgICAgICAgIGdldE9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyKCkubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXy5tZXJnZUZyb20odmFsdWUpOwogICAgICAgIH0KICAgICAgICBpZiAob3B0aW9uYWxBbGxUeXBlc18gIT0gbnVsbCkgewogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxBbGxUeXBlcygpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgb3B0aW9uYWxBbGxUeXBlc18gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgZ2V0T3B0aW9uYWxBbGxUeXBlc0J1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRPcHRpb25hbEFsbFR5cGVzRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvcHRpb25hbF9hbGxfdHlwZXMgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsQWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxBbGxUeXBlc0J1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsQWxsVHlwZXNfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbEFsbFR5cGVzXzsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9wdGlvbmFsX2FsbF90eXBlcyA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEFsbFR5cGVzKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvcHRpb25hbEFsbFR5cGVzXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbEFsbFR5cGVzQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gcmVwZWF0ZWRBbGxUeXBlc18gPQogICAgICAgIGphdmEudXRpbC5Db2xsZWN0aW9ucy5lbXB0eUxpc3QoKTsKICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCEoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18gPSBuZXcgamF2YS51dGlsLkFycmF5TGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPihyZXBlYXRlZEFsbFR5cGVzXyk7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgIH0KICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXzsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRSZXBlYXRlZEFsbFR5cGVzTGlzdCgpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBqYXZhLnV0aWwuQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTGlzdChyZXBlYXRlZEFsbFR5cGVzXyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZUxpc3QoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEFsbFR5cGVzQ291bnQoKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc18uc2l6ZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmdldENvdW50KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldFJlcGVhdGVkQWxsVHlwZXMoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc18uZ2V0KGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlKGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRBbGxUeXBlcygKICAgICAgICAgIGludCBpbmRleCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChyZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEFsbFR5cGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXy5zZXQoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgdmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEFsbFR5cGVzKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEFsbFR5cGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXy5zZXQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRBbGxUeXBlc0lzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18uYWRkKHZhbHVlKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uYWRkTWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkQWxsVHlwZXMoCiAgICAgICAgICBpbnQgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgZW5zdXJlUmVwZWF0ZWRBbGxUeXBlc0lzTXV0YWJsZSgpOwogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18uYWRkKGluZGV4LCB2YWx1ZSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmFkZE1lc3NhZ2UoaW5kZXgsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRBbGxUeXBlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKTsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNfLmFkZChidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmFkZE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEFsbFR5cGVzKAogICAgICAgICAgaW50IGluZGV4LCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEFsbFR5cGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXy5hZGQoaW5kZXgsIGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uYWRkTWVzc2FnZShpbmRleCwgYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRBbGxSZXBlYXRlZEFsbFR5cGVzKAogICAgICAgICAgamF2YS5sYW5nLkl0ZXJhYmxlPD8gZXh0ZW5kcyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiB2YWx1ZXMpIHsKICAgICAgICBpZiAocmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGVuc3VyZVJlcGVhdGVkQWxsVHlwZXNJc011dGFibGUoKTsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkQWxsVHlwZXNfKTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8uYWRkQWxsTWVzc2FnZXModmFsdWVzKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEFsbFR5cGVzKCkgewogICAgICAgIGlmIChyZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc18gPSBqYXZhLnV0aWwuQ29sbGVjdGlvbnMuZW1wdHlMaXN0KCk7CiAgICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVJlcGVhdGVkQWxsVHlwZXMoaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBlbnN1cmVSZXBlYXRlZEFsbFR5cGVzSXNNdXRhYmxlKCk7CiAgICAgICAgICByZXBlYXRlZEFsbFR5cGVzXy5yZW1vdmUoaW5kZXgpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5yZW1vdmUoaW5kZXgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldFJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldFJlcGVhdGVkQWxsVHlwZXNGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBnZXRSZXBlYXRlZEFsbFR5cGVzT3JCdWlsZGVyKAogICAgICAgICAgaW50IGluZGV4KSB7CiAgICAgICAgaWYgKHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc18uZ2V0KGluZGV4KTsgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVwZWF0ZWRBbGxUeXBlc0J1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoaW5kZXgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8PyBleHRlbmRzIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgIGdldFJlcGVhdGVkQWxsVHlwZXNPckJ1aWxkZXJMaXN0KCkgewogICAgICAgIGlmIChyZXBlYXRlZEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyTGlzdCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gamF2YS51dGlsLkNvbGxlY3Rpb25zLnVubW9kaWZpYWJsZUxpc3QocmVwZWF0ZWRBbGxUeXBlc18pOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgcmVwZWF0ZWRfYWxsX3R5cGVzID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGFkZFJlcGVhdGVkQWxsVHlwZXNCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEFsbFR5cGVzRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIHJlcGVhdGVkX2FsbF90eXBlcyA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciBhZGRSZXBlYXRlZEFsbFR5cGVzQnVpbGRlcigKICAgICAgICAgIGludCBpbmRleCkgewogICAgICAgIHJldHVybiBnZXRSZXBlYXRlZEFsbFR5cGVzRmllbGRCdWlsZGVyKCkuYWRkQnVpbGRlcigKICAgICAgICAgICAgaW5kZXgsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSByZXBlYXRlZF9hbGxfdHlwZXMgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXI+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+IAogICAgICAgICAgZ2V0UmVwZWF0ZWRHcm91cEZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAocmVwZWF0ZWRHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlcGVhdGVkR3JvdXBCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlJlcGVhdGVkRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRHcm91cC5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZS5SZXBlYXRlZEdyb3VwT3JCdWlsZGVyPigKICAgICAgICAgICAgICAgICAgcmVwZWF0ZWRHcm91cF8sCiAgICAgICAgICAgICAgICAgICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApLAogICAgICAgICAgICAgICAgICBnZXRQYXJlbnRGb3JDaGlsZHJlbigpLAogICAgICAgICAgICAgICAgICBpc0NsZWFuKCkpOwogICAgICAgICAgcmVwZWF0ZWRHcm91cF8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVwZWF0ZWRHcm91cEJ1aWxkZXJfOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFyc2luZ01lcmdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RQYXJzaW5nTWVyZ2VMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RQYXJzaW5nTWVyZ2VMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdFBhcnNpbmdNZXJnZUxpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0UGFyc2luZ01lcmdlTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0UGFyc2luZ01lcmdlTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfRVhUX0ZJRUxEX05VTUJFUiA9IDEwMDA7CiAgICAvKioKICAgICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IG9wdGlvbmFsRXh0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAgIC5uZXdNZXNzYWdlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhcnNpbmdNZXJnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCksCiAgICAgICAgICAwLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5jbGFzcywKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRVhUX0ZJRUxEX05VTUJFUiA9IDEwMDE7CiAgICAvKioKICAgICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUgeyAuLi4gfTwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLAogICAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+PiByZXBlYXRlZEV4dCA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgICAubmV3TWVzc2FnZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYXJzaW5nTWVyZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpLAogICAgICAgICAgMSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuY2xhc3MsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhbGxFeHRlbnNpb25zIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNBbGxFeHRlbnNpb25zKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGFsbEV4dGVuc2lvbnMuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBnZXRBbGxFeHRlbnNpb25zKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlT3JCdWlsZGVyIGdldEFsbEV4dGVuc2lvbnNPckJ1aWxkZXIoKTsKICB9CiAgLyoqCiAgICogPHByZT4KICAgKiBUZXN0IHRoYXQgdGhlIGNvcnJlY3QgZXhjZXB0aW9uIGlzIHRocm93biBieSBwYXJzZUZyb20gaW4gYSBjb3JuZXIgY2FzZQogICAqIGludm9sdmluZyBtZXJnaW5nLCBleHRlbnNpb25zLCBhbmQgcmVxdWlyZWQgZmllbGRzLgogICAqIDwvcHJlPgogICAqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSkKICAgICAgVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0TWVyZ2VFeGNlcHRpb25MaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0TWVyZ2VFeGNlcHRpb25MaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXJnZUV4Y2VwdGlvbkxpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEFMTF9FWFRFTlNJT05TX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxFeHRlbnNpb25zXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhbGxFeHRlbnNpb25zIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzQWxsRXh0ZW5zaW9ucygpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhbGxFeHRlbnNpb25zLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGdldEFsbEV4dGVuc2lvbnMoKSB7CiAgICAgIHJldHVybiBhbGxFeHRlbnNpb25zXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogYWxsRXh0ZW5zaW9uc187CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciBnZXRBbGxFeHRlbnNpb25zT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gYWxsRXh0ZW5zaW9uc18gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGFsbEV4dGVuc2lvbnNfOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkpIHsKICAgICAgICBpZiAoIWdldEFsbEV4dGVuc2lvbnMoKS5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSgxLCBnZXRBbGxFeHRlbnNpb25zKCkpOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMSwgZ2V0QWxsRXh0ZW5zaW9ucygpKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUpIG9iajsKCiAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkgIT0gb3RoZXIuaGFzQWxsRXh0ZW5zaW9ucygpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkpIHsKICAgICAgICBpZiAoIWdldEFsbEV4dGVuc2lvbnMoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldEFsbEV4dGVuc2lvbnMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBBTExfRVhURU5TSU9OU19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0QWxsRXh0ZW5zaW9ucygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogVGVzdCB0aGF0IHRoZSBjb3JyZWN0IGV4Y2VwdGlvbiBpcyB0aHJvd24gYnkgcGFyc2VGcm9tIGluIGEgY29ybmVyIGNhc2UKICAgICAqIGludm9sdmluZyBtZXJnaW5nLCBleHRlbnNpb25zLCBhbmQgcmVxdWlyZWQgZmllbGRzLgogICAgICogPC9wcmU+CiAgICAgKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewogICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwogICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpIHsKICAgICAgICBpZiAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICBnZXRBbGxFeHRlbnNpb25zRmllbGRCdWlsZGVyKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBhbGxFeHRlbnNpb25zXyA9IG51bGw7CiAgICAgICAgaWYgKGFsbEV4dGVuc2lvbnNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBhbGxFeHRlbnNpb25zQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgYWxsRXh0ZW5zaW9uc0J1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVyZ2VFeGNlcHRpb25MaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmFsbEV4dGVuc2lvbnNfID0gYWxsRXh0ZW5zaW9uc0J1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IGFsbEV4dGVuc2lvbnNfCiAgICAgICAgICAgICAgOiBhbGxFeHRlbnNpb25zQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVyZ2VFeGNlcHRpb25MaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzQWxsRXh0ZW5zaW9ucygpKSB7CiAgICAgICAgICBtZXJnZUFsbEV4dGVuc2lvbnMob3RoZXIuZ2V0QWxsRXh0ZW5zaW9ucygpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGlmIChoYXNBbGxFeHRlbnNpb25zKCkpIHsKICAgICAgICAgIGlmICghZ2V0QWxsRXh0ZW5zaW9ucygpLmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAxMDogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0QWxsRXh0ZW5zaW9uc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTAKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsRXh0ZW5zaW9uc187CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZU9yQnVpbGRlcj4gYWxsRXh0ZW5zaW9uc0J1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGFsbEV4dGVuc2lvbnMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzQWxsRXh0ZW5zaW9ucygpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYWxsRXh0ZW5zaW9ucy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgZ2V0QWxsRXh0ZW5zaW9ucygpIHsKICAgICAgICBpZiAoYWxsRXh0ZW5zaW9uc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBhbGxFeHRlbnNpb25zXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogYWxsRXh0ZW5zaW9uc187CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBhbGxFeHRlbnNpb25zQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0QWxsRXh0ZW5zaW9ucyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAoYWxsRXh0ZW5zaW9uc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgYWxsRXh0ZW5zaW9uc18gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYWxsRXh0ZW5zaW9uc0J1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEFsbEV4dGVuc2lvbnMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAoYWxsRXh0ZW5zaW9uc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUFsbEV4dGVuc2lvbnMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKGFsbEV4dGVuc2lvbnNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkgJiYKICAgICAgICAgICAgYWxsRXh0ZW5zaW9uc18gIT0gbnVsbCAmJgogICAgICAgICAgICBhbGxFeHRlbnNpb25zXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0QWxsRXh0ZW5zaW9uc0J1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYWxsRXh0ZW5zaW9uc18gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgYWxsRXh0ZW5zaW9uc0J1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChhbGxFeHRlbnNpb25zXyAhPSBudWxsKSB7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgYWxsX2V4dGVuc2lvbnMgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQWxsRXh0ZW5zaW9ucygpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgYWxsRXh0ZW5zaW9uc18gPSBudWxsOwogICAgICAgIGlmIChhbGxFeHRlbnNpb25zQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgYWxsRXh0ZW5zaW9uc0J1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIGFsbEV4dGVuc2lvbnNCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLkJ1aWxkZXIgZ2V0QWxsRXh0ZW5zaW9uc0J1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRBbGxFeHRlbnNpb25zRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIGFsbF9leHRlbnNpb25zID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlT3JCdWlsZGVyIGdldEFsbEV4dGVuc2lvbnNPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKGFsbEV4dGVuc2lvbnNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gYWxsRXh0ZW5zaW9uc0J1aWxkZXJfLmdldE1lc3NhZ2VPckJ1aWxkZXIoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGFsbEV4dGVuc2lvbnNfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IGFsbEV4dGVuc2lvbnNfOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSBhbGxfZXh0ZW5zaW9ucyA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldEFsbEV4dGVuc2lvbnNGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKGFsbEV4dGVuc2lvbnNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBhbGxFeHRlbnNpb25zQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRBbGxFeHRlbnNpb25zKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBhbGxFeHRlbnNpb25zXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBhbGxFeHRlbnNpb25zQnVpbGRlcl87CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdE1lcmdlRXhjZXB0aW9uTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWVyZ2VFeGNlcHRpb25MaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RNZXJnZUV4Y2VwdGlvbkxpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXJnZUV4Y2VwdGlvbkxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0RW1wdHlNZXNzYWdlTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKICB9CiAgLyoqCiAgICogPHByZT4KICAgKiBUZXN0RW1wdHlNZXNzYWdlTGl0ZSBpcyB1c2VkIHRvIHRlc3QgdW5rbm93biBmaWVsZHMgc3VwcG9ydCBpbiBsaXRlIG1vZGUuCiAgICogPC9wcmU+CiAgICoKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RFbXB0eU1lc3NhZ2VMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbXB0eU1lc3NhZ2VMaXRlKQogICAgICBUZXN0RW1wdHlNZXNzYWdlTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdEVtcHR5TWVzc2FnZUxpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdEVtcHR5TWVzc2FnZUxpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0RW1wdHlNZXNzYWdlTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0RW1wdHlNZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUpIG9iajsKCiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRlc3RFbXB0eU1lc3NhZ2VMaXRlIGlzIHVzZWQgdG8gdGVzdCB1bmtub3duIGZpZWxkcyBzdXBwb3J0IGluIGxpdGUgbW9kZS4KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbXB0eU1lc3NhZ2VMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEVtcHR5TWVzc2FnZUxpdGUpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlKHRoaXMpOwogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEVtcHR5TWVzc2FnZUxpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0RW1wdHlNZXNzYWdlTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0RW1wdHlNZXNzYWdlTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RFbXB0eU1lc3NhZ2VMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVtcHR5TWVzc2FnZUxpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVtcHR5TWVzc2FnZUxpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy4KICAgICAgICAgIEV4dGVuZGFibGVNZXNzYWdlT3JCdWlsZGVyPFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGU+IHsKICB9CiAgLyoqCiAgICogPHByZT4KICAgKiBMaWtlIGFib3ZlLCBidXQgZGVjbGFyZSBhbGwgZmllbGQgbnVtYmVycyBhcyBwb3RlbnRpYWwgZXh0ZW5zaW9ucy4gIE5vCiAgICogYWN0dWFsIGV4dGVuc2lvbnMgc2hvdWxkIGV2ZXIgYmUgZGVmaW5lZCBmb3IgdGhpcyB0eXBlLgogICAqIDwvcHJlPgogICAqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlTWVzc2FnZTwKICAgICAgICBUZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlPiBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSkKICAgICAgVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkV4dGVuZGFibGVCdWlsZGVyPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUsID8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmICghZXh0ZW5zaW9uc0FyZUluaXRpYWxpemVkKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLkV4dGVuZGFibGVNZXNzYWdlPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGU+LkV4dGVuc2lvbldyaXRlcgogICAgICAgICAgZXh0ZW5zaW9uV3JpdGVyID0gbmV3RXh0ZW5zaW9uV3JpdGVyKCk7CiAgICAgIGV4dGVuc2lvbldyaXRlci53cml0ZVVudGlsKDUzNjg3MDkxMiwgb3V0cHV0KTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHNpemUgKz0gZXh0ZW5zaW9uc1NlcmlhbGl6ZWRTaXplKCk7CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRFeHRlbnNpb25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0RXh0ZW5zaW9uRmllbGRzKCkpKQogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBoYXNoID0gaGFzaEZpZWxkcyhoYXNoLCBnZXRFeHRlbnNpb25GaWVsZHMoKSk7CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIExpa2UgYWJvdmUsIGJ1dCBkZWNsYXJlIGFsbCBmaWVsZCBudW1iZXJzIGFzIHBvdGVudGlhbCBleHRlbnNpb25zLiAgTm8KICAgICAqIGFjdHVhbCBleHRlbnNpb25zIHNob3VsZCBldmVyIGJlIGRlZmluZWQgZm9yIHRoaXMgdHlwZS4KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLCBCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUodGhpcyk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUsIFR5cGU+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIHNldEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIGludCBpbmRleCwgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRFeHRlbnNpb24oZXh0ZW5zaW9uLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIGFkZEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkRXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUPiBCdWlsZGVyIGNsZWFyRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlLCBUPiBleHRlbnNpb24pIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJFeHRlbnNpb24oZXh0ZW5zaW9uKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgdGhpcy5tZXJnZUV4dGVuc2lvbkZpZWxkcyhvdGhlcik7CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGlmICghZXh0ZW5zaW9uc0FyZUluaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFYxTWVzc2FnZUxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVjFNZXNzYWdlTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBpbnRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzSW50RmllbGQoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBpbnRGaWVsZC4KICAgICAqLwogICAgaW50IGdldEludEZpZWxkKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVjFFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYxX0ZJUlNUXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGVudW1GaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzRW51bUZpZWxkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5WMUVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjFfRklSU1RdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGVudW1GaWVsZC4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFFbnVtTGl0ZSBnZXRFbnVtRmllbGQoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVjFNZXNzYWdlTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFYxTWVzc2FnZUxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVjFNZXNzYWdlTGl0ZSkKICAgICAgVjFNZXNzYWdlTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVjFNZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBWMU1lc3NhZ2VMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVjFNZXNzYWdlTGl0ZSgpIHsKICAgICAgZW51bUZpZWxkXyA9IDE7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVjFNZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1YxTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBJTlRfRklFTERfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgaW50IGludEZpZWxkXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBpbnRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0ludEZpZWxkKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgaW50RmllbGQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0SW50RmllbGQoKSB7CiAgICAgIHJldHVybiBpbnRGaWVsZF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRU5VTV9GSUVMRF9GSUVMRF9OVU1CRVIgPSAyOwogICAgcHJpdmF0ZSBpbnQgZW51bUZpZWxkXyA9IDE7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5WMUVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjFfRklSU1RdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZW51bUZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNFbnVtRmllbGQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlYxRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMV9GSVJTVF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZW51bUZpZWxkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMUVudW1MaXRlIGdldEVudW1GaWVsZCgpIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFFbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMUVudW1MaXRlLmZvck51bWJlcihlbnVtRmllbGRfKTsKICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFFbnVtTGl0ZS5WMV9GSVJTVCA6IHJlc3VsdDsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBpZiAoIWhhc0ludEZpZWxkKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGludEZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSgyLCBlbnVtRmllbGRfKTsKICAgICAgfQogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZSgxLCBpbnRGaWVsZF8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZSgyLCBlbnVtRmllbGRfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUpIG9iajsKCiAgICAgIGlmIChoYXNJbnRGaWVsZCgpICE9IG90aGVyLmhhc0ludEZpZWxkKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0ludEZpZWxkKCkpIHsKICAgICAgICBpZiAoZ2V0SW50RmllbGQoKQogICAgICAgICAgICAhPSBvdGhlci5nZXRJbnRGaWVsZCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0VudW1GaWVsZCgpICE9IG90aGVyLmhhc0VudW1GaWVsZCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNFbnVtRmllbGQoKSkgewogICAgICAgIGlmIChlbnVtRmllbGRfICE9IG90aGVyLmVudW1GaWVsZF8pIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNJbnRGaWVsZCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgSU5UX0ZJRUxEX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRJbnRGaWVsZCgpOwogICAgICB9CiAgICAgIGlmIChoYXNFbnVtRmllbGQoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEVOVU1fRklFTERfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGVudW1GaWVsZF87CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5WMU1lc3NhZ2VMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVjFNZXNzYWdlTGl0ZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMU1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBpbnRGaWVsZF8gPSAwOwogICAgICAgIGVudW1GaWVsZF8gPSAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVjFNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5pbnRGaWVsZF8gPSBpbnRGaWVsZF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuZW51bUZpZWxkXyA9IGVudW1GaWVsZF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKG90aGVyLmhhc0ludEZpZWxkKCkpIHsKICAgICAgICAgIHNldEludEZpZWxkKG90aGVyLmdldEludEZpZWxkKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRW51bUZpZWxkKCkpIHsKICAgICAgICAgIHNldEVudW1GaWVsZChvdGhlci5nZXRFbnVtRmllbGQoKSk7CiAgICAgICAgfQogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICBpZiAoIWhhc0ludEZpZWxkKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIGludEZpZWxkXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgKICAgICAgICAgICAgICBjYXNlIDE2OiB7CiAgICAgICAgICAgICAgICBpbnQgdG1wUmF3ID0gaW5wdXQucmVhZEVudW0oKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUgdG1wVmFsdWUgPQogICAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCgyLCB0bXBSYXcpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZW51bUZpZWxkXyA9IHRtcFJhdzsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IGludEZpZWxkXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBpbnRfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBpbnRGaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0ludEZpZWxkKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGludEZpZWxkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEludEZpZWxkKCkgewogICAgICAgIHJldHVybiBpbnRGaWVsZF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGludEZpZWxkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0SW50RmllbGQoaW50IHZhbHVlKSB7CgogICAgICAgIGludEZpZWxkXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFySW50RmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGludEZpZWxkXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgaW50IGVudW1GaWVsZF8gPSAxOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlYxRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMV9GSVJTVF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGVudW1GaWVsZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc0VudW1GaWVsZCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5WMUVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjFfRklSU1RdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZW51bUZpZWxkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFFbnVtTGl0ZSBnZXRFbnVtRmllbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjFFbnVtTGl0ZSByZXN1bHQgPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMUVudW1MaXRlLmZvck51bWJlcihlbnVtRmllbGRfKTsKICAgICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMUVudW1MaXRlLlYxX0ZJUlNUIDogcmVzdWx0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVjFFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYxX0ZJUlNUXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZW51bUZpZWxkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RW51bUZpZWxkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxRW51bUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBlbnVtRmllbGRfID0gdmFsdWUuZ2V0TnVtYmVyKCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5WMUVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjFfRklSU1RdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJFbnVtRmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgIGVudW1GaWVsZF8gPSAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlYxTWVzc2FnZUxpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlYxTWVzc2FnZUxpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYxTWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxWMU1lc3NhZ2VMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFYxTWVzc2FnZUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBWMU1lc3NhZ2VMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VjFNZXNzYWdlTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxWMU1lc3NhZ2VMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMU1lc3NhZ2VMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVjJNZXNzYWdlTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5WMk1lc3NhZ2VMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGludEZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNJbnRGaWVsZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBpbnRfZmllbGQgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGludEZpZWxkLgogICAgICovCiAgICBpbnQgZ2V0SW50RmllbGQoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5WMkVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjJfRklSU1RdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZW51bUZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNFbnVtRmllbGQoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlYyRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMl9GSVJTVF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZW51bUZpZWxkLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIGdldEVudW1GaWVsZCgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5WMk1lc3NhZ2VMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVjJNZXNzYWdlTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5WMk1lc3NhZ2VMaXRlKQogICAgICBWMk1lc3NhZ2VMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBWMk1lc3NhZ2VMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFYyTWVzc2FnZUxpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBWMk1lc3NhZ2VMaXRlKCkgewogICAgICBlbnVtRmllbGRfID0gMTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBWMk1lc3NhZ2VMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVjJNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IElOVF9GSUVMRF9GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBpbnQgaW50RmllbGRfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGludEZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzSW50RmllbGQoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBpbnRGaWVsZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRJbnRGaWVsZCgpIHsKICAgICAgcmV0dXJuIGludEZpZWxkXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFTlVNX0ZJRUxEX0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIGludCBlbnVtRmllbGRfID0gMTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlYyRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMl9GSVJTVF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBlbnVtRmllbGQgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlIHB1YmxpYyBib29sZWFuIGhhc0VudW1GaWVsZCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVjJFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYyX0ZJUlNUXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtRmllbGQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUgZ2V0RW51bUZpZWxkKCkgewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuZm9yTnVtYmVyKGVudW1GaWVsZF8pOwogICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlLlYyX0ZJUlNUIDogcmVzdWx0OwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmICghaGFzSW50RmllbGQoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMSwgaW50RmllbGRfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVFbnVtKDIsIGVudW1GaWVsZF8pOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDEsIGludEZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZUVudW1TaXplKDIsIGVudW1GaWVsZF8pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc0ludEZpZWxkKCkgIT0gb3RoZXIuaGFzSW50RmllbGQoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzSW50RmllbGQoKSkgewogICAgICAgIGlmIChnZXRJbnRGaWVsZCgpCiAgICAgICAgICAgICE9IG90aGVyLmdldEludEZpZWxkKCkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoaGFzRW51bUZpZWxkKCkgIT0gb3RoZXIuaGFzRW51bUZpZWxkKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0VudW1GaWVsZCgpKSB7CiAgICAgICAgaWYgKGVudW1GaWVsZF8gIT0gb3RoZXIuZW51bUZpZWxkXykgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0ludEZpZWxkKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBJTlRfRklFTERfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEludEZpZWxkKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc0VudW1GaWVsZCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgRU5VTV9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZW51bUZpZWxkXzsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlYyTWVzc2FnZUxpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5WMk1lc3NhZ2VMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGludEZpZWxkXyA9IDA7CiAgICAgICAgZW51bUZpZWxkXyA9IDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmludEZpZWxkXyA9IGludEZpZWxkXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5lbnVtRmllbGRfID0gZW51bUZpZWxkXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzSW50RmllbGQoKSkgewogICAgICAgICAgc2V0SW50RmllbGQob3RoZXIuZ2V0SW50RmllbGQoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNFbnVtRmllbGQoKSkgewogICAgICAgICAgc2V0RW51bUZpZWxkKG90aGVyLmdldEVudW1GaWVsZCgpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIGlmICghaGFzSW50RmllbGQoKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgODogewogICAgICAgICAgICAgICAgaW50RmllbGRfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGNhc2UgMTY6IHsKICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSB0bXBWYWx1ZSA9CiAgICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZS5mb3JOdW1iZXIodG1wUmF3KTsKICAgICAgICAgICAgICAgIGlmICh0bXBWYWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93blZhcmludEZpZWxkKDIsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBlbnVtRmllbGRfID0gdG1wUmF3OwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBpbnQgaW50RmllbGRfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGludF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGludEZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzSW50RmllbGQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBpbnRfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgaW50RmllbGQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0SW50RmllbGQoKSB7CiAgICAgICAgcmV0dXJuIGludEZpZWxkXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgaW50X2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgaW50RmllbGQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRJbnRGaWVsZChpbnQgdmFsdWUpIHsKCiAgICAgICAgaW50RmllbGRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBpbnRfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJJbnRGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgaW50RmllbGRfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZW51bUZpZWxkXyA9IDE7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuVjJFbnVtTGl0ZSBlbnVtX2ZpZWxkID0gMiBbZGVmYXVsdCA9IFYyX0ZJUlNUXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZW51bUZpZWxkIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzRW51bUZpZWxkKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlYyRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMl9GSVJTVF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtRmllbGQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIGdldEVudW1GaWVsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuZm9yTnVtYmVyKGVudW1GaWVsZF8pOwogICAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuVjJfRklSU1QgOiByZXN1bHQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5WMkVudW1MaXRlIGVudW1fZmllbGQgPSAyIFtkZWZhdWx0ID0gVjJfRklSU1RdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBlbnVtRmllbGQgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRFbnVtRmllbGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIGVudW1GaWVsZF8gPSB2YWx1ZS5nZXROdW1iZXIoKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlYyRW51bUxpdGUgZW51bV9maWVsZCA9IDIgW2RlZmF1bHQgPSBWMl9GSVJTVF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckVudW1GaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgZW51bUZpZWxkXyA9IDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVjJNZXNzYWdlTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVjJNZXNzYWdlTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJNZXNzYWdlTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFYyTWVzc2FnZUxpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VjJNZXNzYWdlTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFYyTWVzc2FnZUxpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxWMk1lc3NhZ2VMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFYyTWVzc2FnZUxpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyTWVzc2FnZUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy4KICAgICAgICAgIEV4dGVuZGFibGVNZXNzYWdlT3JCdWlsZGVyPFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZT4gewoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSA1MzY4NzAwMDA7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEludDMyIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gNTM2ODcwMDAwOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsSW50MzIuCiAgICAgKi8KICAgIGludCBnZXRPcHRpb25hbEludDMyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBmaXhlZF8zMiA9IDUzNjg3MDAwMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0ZpeGVkMzIoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZml4ZWRfMzIgPSA1MzY4NzAwMDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgZml4ZWQzMi4KICAgICAqLwogICAgaW50IGdldEZpeGVkMzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbnQzMi4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IGdldFJlcGVhdGVkSW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbnQzMi4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkSW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA1MzY4NzAwMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHBhY2tlZEludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UGFja2VkSW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDUzNjg3MDAwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcGFja2VkSW50MzIuCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRJbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDUzNjg3MDAwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIGludCBnZXRQYWNrZWRJbnQzMihpbnQgaW5kZXgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9lbnVtID0gNTM2ODcwMDA0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxFbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEVudW0oKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9lbnVtID0gNTM2ODcwMDA0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldE9wdGlvbmFsRW51bSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbFN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gNTM2ODcwMDA1OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU3RyaW5nLgogICAgICovCiAgICBqYXZhLmxhbmcuU3RyaW5nIGdldE9wdGlvbmFsU3RyaW5nKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9wdGlvbmFsU3RyaW5nLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPcHRpb25hbFN0cmluZ0J5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDUzNjg3MDAwNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09wdGlvbmFsQnl0ZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSA1MzY4NzAwMDY7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxCeXRlcy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9wdGlvbmFsQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsTWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT3B0aW9uYWxNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbE1lc3NhZ2UuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRPcHRpb25hbE1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIGdldE9wdGlvbmFsTWVzc2FnZU9yQnVpbGRlcigpOwoKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDUzNjg3MDAwOCB7IC4uLiB9PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbGdyb3VwIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPcHRpb25hbEdyb3VwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsZ3JvdXAuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIGdldE9wdGlvbmFsR3JvdXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDUzNjg3MDAwOCB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlciBnZXRPcHRpb25hbEdyb3VwT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFN0cmluZ1N0cmluZ01hcENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgc3RyaW5nX3N0cmluZ19tYXAgPSA1MzY4NzAwMTA7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zU3RyaW5nU3RyaW5nTWFwKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0U3RyaW5nU3RyaW5nTWFwTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgZ2V0U3RyaW5nU3RyaW5nTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgc3RyaW5nX3N0cmluZ19tYXAgPSA1MzY4NzAwMTA7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICBnZXRTdHJpbmdTdHJpbmdNYXBNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBzdHJpbmdfc3RyaW5nX21hcCA9IDUzNjg3MDAxMDs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZ2V0U3RyaW5nU3RyaW5nTWFwT3JEZWZhdWx0KAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBzdHJpbmdfc3RyaW5nX21hcCA9IDUzNjg3MDAxMDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0U3RyaW5nU3RyaW5nTWFwT3JUaHJvdygKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gNTM2ODcwMDExOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mVWludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSA1MzY4NzAwMTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZVaW50MzIuCiAgICAgKi8KICAgIGludCBnZXRPbmVvZlVpbnQzMigpOwoKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlRlc3RBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZUZXN0QWxsVHlwZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZUZXN0QWxsVHlwZXMuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T25lb2ZUZXN0QWxsVHlwZXMoKTsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9uZW9mVGVzdEFsbFR5cGVzT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gNTM2ODcwMDEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mU3RyaW5nKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSA1MzY4NzAwMTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9uZW9mU3RyaW5nQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNTM2ODcwMDE0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZCeXRlcygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDUzNjg3MDAxNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlcygpOwoKICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PbmVvZkZpZWxkQ2FzZSBnZXRPbmVvZkZpZWxkQ2FzZSgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlTWVzc2FnZTwKICAgICAgICBUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGU+IGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUpCiAgICAgIFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlQnVpbGRlcjxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUsID8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSgpIHsKICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgcGFja2VkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIG9wdGlvbmFsRW51bV8gPSA0OwogICAgICBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgICAgb3B0aW9uYWxCeXRlc18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkUmVmbGVjdGlvbkFjY2Vzc29yIGludGVybmFsR2V0TWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgIGludCBudW1iZXIpIHsKICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICBjYXNlIDUzNjg3MDAxMDoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgfQogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBpbnRlcmZhY2UgT3B0aW9uYWxHcm91cE9yQnVpbGRlciBleHRlbmRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZ3JvdXBfYSA9IDUzNjg3MDAwOTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgZ3JvdXBBIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIGJvb2xlYW4gaGFzR3JvdXBBKCk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBncm91cF9hID0gNTM2ODcwMDA5OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZ3JvdXBBLgogICAgICAgKi8KICAgICAgaW50IGdldEdyb3VwQSgpOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cH0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBPcHRpb25hbEdyb3VwIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgICBPcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgICAvLyBVc2UgT3B0aW9uYWxHcm91cC5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgICBwcml2YXRlIE9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBPcHRpb25hbEdyb3VwKCkgewogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgICByZXR1cm4gbmV3IE9wdGlvbmFsR3JvdXAoKTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX09wdGlvbmFsR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBHUk9VUF9BX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAwOTsKICAgICAgcHJpdmF0ZSBpbnQgZ3JvdXBBXyA9IDA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBncm91cF9hID0gNTM2ODcwMDA5OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBncm91cEEgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNHcm91cEEoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBncm91cF9hID0gNTM2ODcwMDA5OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgZ3JvdXBBLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEdyb3VwQSgpIHsKICAgICAgICByZXR1cm4gZ3JvdXBBXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIG91dHB1dC53cml0ZUludDMyKDUzNjg3MDAwOSwgZ3JvdXBBXyk7CiAgICAgICAgfQogICAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICAgIHNpemUgPSAwOwogICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDUzNjg3MDAwOSwgZ3JvdXBBXyk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgICByZXR1cm4gc2l6ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwKSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICAgIH0KICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCkgb2JqOwoKICAgICAgICBpZiAoaGFzR3JvdXBBKCkgIT0gb3RoZXIuaGFzR3JvdXBBKCkpIHJldHVybiBmYWxzZTsKICAgICAgICBpZiAoaGFzR3JvdXBBKCkpIHsKICAgICAgICAgIGlmIChnZXRHcm91cEEoKQogICAgICAgICAgICAgICE9IG90aGVyLmdldEdyb3VwQSgpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgICB9CiAgICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgICBpZiAoaGFzR3JvdXBBKCkpIHsKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEdST1VQX0FfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0R3JvdXBBKCk7CiAgICAgICAgfQogICAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICAgIHJldHVybiBoYXNoOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQoKICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBwYXJzZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHBhcnNlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgICB9CiAgICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHByb3RvdHlwZSkgewogICAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwfQogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCkKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyIHsKICAgICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9PcHRpb25hbEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlci5jbGFzcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAubmV3QnVpbGRlcigpCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgICBncm91cEFfID0gMDsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3I7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIGJ1aWxkKCkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCh0aGlzKTsKICAgICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgcmVzdWx0KSB7CiAgICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICAgIHJlc3VsdC5ncm91cEFfID0gZ3JvdXBBXzsKICAgICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwKSB7CiAgICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwKW90aGVyKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIG90aGVyKSB7CiAgICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgICAgaWYgKG90aGVyLmhhc0dyb3VwQSgpKSB7CiAgICAgICAgICAgIHNldEdyb3VwQShvdGhlci5nZXRHcm91cEEoKSk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIC03MjI0OiB7CiAgICAgICAgICAgICAgICAgIGdyb3VwQV8gPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzIyNAogICAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgICAgcHJpdmF0ZSBpbnQgZ3JvdXBBXyA7CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZ3JvdXBfYSA9IDUzNjg3MDAwOTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBncm91cEEgZmllbGQgaXMgc2V0LgogICAgICAgICAqLwogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgYm9vbGVhbiBoYXNHcm91cEEoKSB7CiAgICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGdyb3VwX2EgPSA1MzY4NzAwMDk7PC9jb2RlPgogICAgICAgICAqIEByZXR1cm4gVGhlIGdyb3VwQS4KICAgICAgICAgKi8KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGludCBnZXRHcm91cEEoKSB7CiAgICAgICAgICByZXR1cm4gZ3JvdXBBXzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZ3JvdXBfYSA9IDUzNjg3MDAwOTs8L2NvZGU+CiAgICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBncm91cEEgdG8gc2V0LgogICAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBzZXRHcm91cEEoaW50IHZhbHVlKSB7CgogICAgICAgICAgZ3JvdXBBXyA9IHZhbHVlOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZ3JvdXBfYSA9IDUzNjg3MDAwOTs8L2NvZGU+CiAgICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyR3JvdXBBKCkgewogICAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgICAgZ3JvdXBBXyA9IDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICAgIH0KCgogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwKQogICAgICB9CgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXApCiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIHN0YXRpYyB7CiAgICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCgpOwogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8T3B0aW9uYWxHcm91cD4KICAgICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPE9wdGlvbmFsR3JvdXA+KCkgewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgT3B0aW9uYWxHcm91cCBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE9wdGlvbmFsR3JvdXA+IHBhcnNlcigpIHsKICAgICAgICByZXR1cm4gUEFSU0VSOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxPcHRpb25hbEdyb3VwPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBQQVJTRVI7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICAgIH0KCiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHByaXZhdGUgaW50IG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBvbmVvZkZpZWxkXzsKICAgIHB1YmxpYyBlbnVtIE9uZW9mRmllbGRDYXNlCiAgICAgICAgaW1wbGVtZW50cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlLAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZS5JbnRlcm5hbE9uZU9mRW51bSB7CiAgICAgIE9ORU9GX1VJTlQzMig1MzY4NzAwMTEpLAogICAgICBPTkVPRl9URVNUX0FMTF9UWVBFUyg1MzY4NzAwMTIpLAogICAgICBPTkVPRl9TVFJJTkcoNTM2ODcwMDEzKSwKICAgICAgT05FT0ZfQllURVMoNTM2ODcwMDE0KSwKICAgICAgT05FT0ZGSUVMRF9OT1RfU0VUKDApOwogICAgICBwcml2YXRlIGZpbmFsIGludCB2YWx1ZTsKICAgICAgcHJpdmF0ZSBPbmVvZkZpZWxkQ2FzZShpbnQgdmFsdWUpIHsKICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtYmVyIG9mIHRoZSBlbnVtIHRvIGxvb2sgZm9yLgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtYmVyLgogICAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgc3RhdGljIE9uZW9mRmllbGRDYXNlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgT25lb2ZGaWVsZENhc2UgZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICAgIGNhc2UgNTM2ODcwMDExOiByZXR1cm4gT05FT0ZfVUlOVDMyOwogICAgICAgICAgY2FzZSA1MzY4NzAwMTI6IHJldHVybiBPTkVPRl9URVNUX0FMTF9UWVBFUzsKICAgICAgICAgIGNhc2UgNTM2ODcwMDEzOiByZXR1cm4gT05FT0ZfU1RSSU5HOwogICAgICAgICAgY2FzZSA1MzY4NzAwMTQ6IHJldHVybiBPTkVPRl9CWVRFUzsKICAgICAgICAgIGNhc2UgMDogcmV0dXJuIE9ORU9GRklFTERfTk9UX1NFVDsKICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE51bWJlcigpIHsKICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgT25lb2ZGaWVsZENhc2UKICAgIGdldE9uZW9mRmllbGRDYXNlKCkgewogICAgICByZXR1cm4gT25lb2ZGaWVsZENhc2UuZm9yTnVtYmVyKAogICAgICAgICAgb25lb2ZGaWVsZENhc2VfKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9JTlQzMl9GSUVMRF9OVU1CRVIgPSA1MzY4NzAwMDA7CiAgICBwcml2YXRlIGludCBvcHRpb25hbEludDMyXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gNTM2ODcwMDAwOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsSW50MzIoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSA1MzY4NzAwMDA7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRPcHRpb25hbEludDMyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxJbnQzMl87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRklYRURfMzJfRklFTERfTlVNQkVSID0gNTM2ODcwMDAxOwogICAgcHJpdmF0ZSBpbnQgZml4ZWQzMl8gPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBmaXhlZF8zMiA9IDUzNjg3MDAwMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNGaXhlZDMyKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGZpeGVkXzMyID0gNTM2ODcwMDAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGZpeGVkMzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0Rml4ZWQzMigpIHsKICAgICAgcmV0dXJuIGZpeGVkMzJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAwMjsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRJbnQzMl8gPQogICAgICAgIGVtcHR5SW50TGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRSZXBlYXRlZEludDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfLmdldEludChpbmRleCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAwMzsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcGFja2VkSW50MzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRJbnQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFBhY2tlZEludDMyTGlzdCgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRJbnQzMi4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcGFja2VkSW50MzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHBhY2tlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRQYWNrZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHBhY2tlZEludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcGFja2VkSW50MzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplID0gLTE7CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfRU5VTV9GSUVMRF9OVU1CRVIgPSA1MzY4NzAwMDQ7CiAgICBwcml2YXRlIGludCBvcHRpb25hbEVudW1fID0gNDsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9lbnVtID0gNTM2ODcwMDA0OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxFbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEVudW0oKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9lbnVtID0gNTM2ODcwMDA0OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsRW51bS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZSBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldE9wdGlvbmFsRW51bSgpIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5mb3JOdW1iZXIob3B0aW9uYWxFbnVtXyk7CiAgICAgIHJldHVybiByZXN1bHQgPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5GT1JFSUdOX0xJVEVfRk9PIDogcmVzdWx0OwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NUUklOR19GSUVMRF9OVU1CRVIgPSA1MzY4NzAwMDU7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgdm9sYXRpbGUgamF2YS5sYW5nLk9iamVjdCBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxTdHJpbmcoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbFN0cmluZy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T3B0aW9uYWxTdHJpbmcoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gb3B0aW9uYWxTdHJpbmdfOwogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9wdGlvbmFsU3RyaW5nLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T3B0aW9uYWxTdHJpbmdCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ187CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGI7CiAgICAgICAgcmV0dXJuIGI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0JZVEVTX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAwNjsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIG9wdGlvbmFsQnl0ZXNfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDUzNjg3MDAwNjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEJ5dGVzKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIG9wdGlvbmFsX2J5dGVzID0gNTM2ODcwMDA2OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsQnl0ZXMuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T3B0aW9uYWxCeXRlcygpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsQnl0ZXNfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX01FU1NBR0VfRklFTERfTlVNQkVSID0gNTM2ODcwMDA3OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxNZXNzYWdlXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxNZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxNZXNzYWdlKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbE1lc3NhZ2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0T3B0aW9uYWxNZXNzYWdlKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxNZXNzYWdlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxNZXNzYWdlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBvcHRpb25hbE1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbE1lc3NhZ2VfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMR1JPVVBfRklFTERfTlVNQkVSID0gNTM2ODcwMDA4OwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBvcHRpb25hbEdyb3VwXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDUzNjg3MDAwOCB7IC4uLiB9PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbGdyb3VwIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwNDApICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gNTM2ODcwMDA4IHsgLi4uIH08L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbGdyb3VwLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgZ2V0T3B0aW9uYWxHcm91cCgpIHsKICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gNTM2ODcwMDA4IHsgLi4uIH08L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlciBnZXRPcHRpb25hbEdyb3VwT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gb3B0aW9uYWxHcm91cF8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLmdldERlZmF1bHRJbnN0YW5jZSgpIDogb3B0aW9uYWxHcm91cF87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgU1RSSU5HX1NUUklOR19NQVBfRklFTERfTlVNQkVSID0gNTM2ODcwMDEwOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgU3RyaW5nU3RyaW5nTWFwRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX1N0cmluZ1N0cmluZ01hcEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNUUklORywKICAgICAgICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU1RSSU5HLAogICAgICAgICAgICAgICAgICAiIik7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBzdHJpbmdTdHJpbmdNYXBfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICBpbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgaWYgKHN0cmluZ1N0cmluZ01hcF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIFN0cmluZ1N0cmluZ01hcERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBzdHJpbmdTdHJpbmdNYXBfOwogICAgfQogICAgcHVibGljIGludCBnZXRTdHJpbmdTdHJpbmdNYXBDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNTdHJpbmdTdHJpbmdNYXAoCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgIHJldHVybiBpbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldFN0cmluZ1N0cmluZ01hcE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IGdldFN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgcmV0dXJuIGdldFN0cmluZ1N0cmluZ01hcE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0U3RyaW5nU3RyaW5nTWFwTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBzdHJpbmdfc3RyaW5nX21hcCA9IDUzNjg3MDAxMDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGdldFN0cmluZ1N0cmluZ01hcE9yRGVmYXVsdCgKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewogICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0U3RyaW5nU3RyaW5nTWFwT3JUaHJvdygKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSkgewogICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9VSU5UMzJfRklFTERfTlVNQkVSID0gNTM2ODcwMDExOwogICAgLyoqCiAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gNTM2ODcwMDExOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZVaW50MzIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlVpbnQzMigpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTE7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnVpbnQzMiBvbmVvZl91aW50MzIgPSA1MzY4NzAwMTE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZVaW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0T25lb2ZVaW50MzIoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDExKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfVEVTVF9BTExfVFlQRVNfRklFTERfTlVNQkVSID0gNTM2ODcwMDEyOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mVGVzdEFsbFR5cGVzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZUZXN0QWxsVHlwZXMoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlRlc3RBbGxUeXBlcy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T25lb2ZUZXN0QWxsVHlwZXMoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T25lb2ZUZXN0QWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfU1RSSU5HX0ZJRUxEX05VTUJFUiA9IDUzNjg3MDAxMzsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZTdHJpbmcoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEzOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gNTM2ODcwMDEzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTMpIHsKICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkgJiYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTMpKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSA1MzY4NzAwMTM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTMpIHsKICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jb3B5RnJvbVV0ZjgoCiAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMykgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBiOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfQllURVNfRklFTERfTlVNQkVSID0gNTM2ODcwMDE0OwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDUzNjg3MDAxNDs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxNDsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA1MzY4NzAwMTQ7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlcy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPbmVvZkJ5dGVzKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxNCkgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGlmICghZXh0ZW5zaW9uc0FyZUluaXRpYWxpemVkKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLkV4dGVuZGFibGVNZXNzYWdlPGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZT4uRXh0ZW5zaW9uV3JpdGVyCiAgICAgICAgICBleHRlbnNpb25Xcml0ZXIgPSBuZXdFeHRlbnNpb25Xcml0ZXIoKTsKICAgICAgZXh0ZW5zaW9uV3JpdGVyLndyaXRlVW50aWwoNTM2ODcwMDAwLCBvdXRwdXQpOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMig1MzY4NzAwMDAsIG9wdGlvbmFsSW50MzJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMig1MzY4NzAwMDEsIGZpeGVkMzJfKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkSW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoNTM2ODcwMDAyLCByZXBlYXRlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRJbnQzMkxpc3QoKS5zaXplKCkgPiAwKSB7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcoLTcyNzApOwogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKHBhY2tlZEludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMk5vVGFnKHBhY2tlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUVudW0oNTM2ODcwMDA0LCBvcHRpb25hbEVudW1fKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDUzNjg3MDAwNSwgb3B0aW9uYWxTdHJpbmdfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVCeXRlcyg1MzY4NzAwMDYsIG9wdGlvbmFsQnl0ZXNfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDUzNjg3MDAwNywgZ2V0T3B0aW9uYWxNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUdyb3VwKDUzNjg3MDAwOCwgZ2V0T3B0aW9uYWxHcm91cCgpKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVTdHJpbmdNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCksCiAgICAgICAgICBTdHJpbmdTdHJpbmdNYXBEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgNTM2ODcwMDEwKTsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTEpIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzIoCiAgICAgICAgICAgIDUzNjg3MDAxMSwgKGludCkoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgb3V0cHV0LndyaXRlTWVzc2FnZSg1MzY4NzAwMTIsIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTMpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDUzNjg3MDAxMywgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDE0KSB7CiAgICAgICAgb3V0cHV0LndyaXRlQnl0ZXMoCiAgICAgICAgICAgIDUzNjg3MDAxNCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDUzNjg3MDAwMCwgb3B0aW9uYWxJbnQzMl8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoNTM2ODcwMDAxLCBmaXhlZDMyXyk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEludDMyXy5zaXplKCk7IGkrKykgewogICAgICAgICAgZGF0YVNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKHJlcGVhdGVkSW50MzJfLmdldEludChpKSk7CiAgICAgICAgfQogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgc2l6ZSArPSA1ICogZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5zaXplKCk7CiAgICAgIH0KICAgICAgewogICAgICAgIGludCBkYXRhU2l6ZSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYWNrZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhwYWNrZWRJbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBpZiAoIWdldFBhY2tlZEludDMyTGlzdCgpLmlzRW1wdHkoKSkgewogICAgICAgICAgc2l6ZSArPSA1OwogICAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhkYXRhU2l6ZSk7CiAgICAgICAgfQogICAgICAgIHBhY2tlZEludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA0KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVFbnVtU2l6ZSg1MzY4NzAwMDQsIG9wdGlvbmFsRW51bV8pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDA4KSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoNTM2ODcwMDA1LCBvcHRpb25hbFN0cmluZ18pOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemUoNTM2ODcwMDA2LCBvcHRpb25hbEJ5dGVzXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDUzNjg3MDAwNywgZ2V0T3B0aW9uYWxNZXNzYWdlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVHcm91cFNpemUoNTM2ODcwMDA4LCBnZXRPcHRpb25hbEdyb3VwKCkpOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgIHN0cmluZ1N0cmluZ01hcF9fID0gU3RyaW5nU3RyaW5nTWFwRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg1MzY4NzAwMTAsIHN0cmluZ1N0cmluZ01hcF9fKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVVSW50MzJTaXplKAogICAgICAgICAgICAgIDUzNjg3MDAxMSwgKGludCkoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDUzNjg3MDAxMiwgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMykgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuY29tcHV0ZVN0cmluZ1NpemUoNTM2ODcwMDEzLCBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTQpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlQnl0ZXNTaXplKAogICAgICAgICAgICAgIDUzNjg3MDAxNCwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIHNpemUgKz0gZXh0ZW5zaW9uc1NlcmlhbGl6ZWRTaXplKCk7CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIG90aGVyID0gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc09wdGlvbmFsSW50MzIoKSAhPSBvdGhlci5oYXNPcHRpb25hbEludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsSW50MzIoKSkgewogICAgICAgIGlmIChnZXRPcHRpb25hbEludDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T3B0aW9uYWxJbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc0ZpeGVkMzIoKSAhPSBvdGhlci5oYXNGaXhlZDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0ZpeGVkMzIoKSkgewogICAgICAgIGlmIChnZXRGaXhlZDMyKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0Rml4ZWQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFnZXRSZXBlYXRlZEludDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkSW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0UGFja2VkSW50MzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UGFja2VkSW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNPcHRpb25hbEVudW0oKSAhPSBvdGhlci5oYXNPcHRpb25hbEVudW0oKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxFbnVtKCkpIHsKICAgICAgICBpZiAob3B0aW9uYWxFbnVtXyAhPSBvdGhlci5vcHRpb25hbEVudW1fKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU3RyaW5nKCkgIT0gb3RoZXIuaGFzT3B0aW9uYWxTdHJpbmcoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxTdHJpbmcoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxTdHJpbmcoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9wdGlvbmFsU3RyaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsQnl0ZXMoKSAhPSBvdGhlci5oYXNPcHRpb25hbEJ5dGVzKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsQnl0ZXMoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxCeXRlcygpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxCeXRlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbE1lc3NhZ2UoKSAhPSBvdGhlci5oYXNPcHRpb25hbE1lc3NhZ2UoKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoaGFzT3B0aW9uYWxNZXNzYWdlKCkpIHsKICAgICAgICBpZiAoIWdldE9wdGlvbmFsTWVzc2FnZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxNZXNzYWdlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSAhPSBvdGhlci5oYXNPcHRpb25hbEdyb3VwKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgIGlmICghZ2V0T3B0aW9uYWxHcm91cCgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T3B0aW9uYWxHcm91cCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldE9uZW9mRmllbGRDYXNlKCkuZXF1YWxzKG90aGVyLmdldE9uZW9mRmllbGRDYXNlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHN3aXRjaCAob25lb2ZGaWVsZENhc2VfKSB7CiAgICAgICAgY2FzZSA1MzY4NzAwMTE6CiAgICAgICAgICBpZiAoZ2V0T25lb2ZVaW50MzIoKQogICAgICAgICAgICAgICE9IG90aGVyLmdldE9uZW9mVWludDMyKCkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNTM2ODcwMDEyOgogICAgICAgICAgaWYgKCFnZXRPbmVvZlRlc3RBbGxUeXBlcygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZlRlc3RBbGxUeXBlcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1MzY4NzAwMTM6CiAgICAgICAgICBpZiAoIWdldE9uZW9mU3RyaW5nKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mU3RyaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDUzNjg3MDAxNDoKICAgICAgICAgIGlmICghZ2V0T25lb2ZCeXRlcygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZkJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDA6CiAgICAgICAgZGVmYXVsdDoKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldEV4dGVuc2lvbkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRFeHRlbnNpb25GaWVsZHMoKSkpCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNPcHRpb25hbEludDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T3B0aW9uYWxJbnQzMigpOwogICAgICB9CiAgICAgIGlmIChoYXNGaXhlZDMyKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBGSVhFRF8zMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0Rml4ZWQzMigpOwogICAgICB9CiAgICAgIGlmIChnZXRSZXBlYXRlZEludDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChnZXRQYWNrZWRJbnQzMkNvdW50KCkgPiAwKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFDS0VEX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRQYWNrZWRJbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbEVudW0oKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIG9wdGlvbmFsRW51bV87CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsU3RyaW5nKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPUFRJT05BTF9TVFJJTkdfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsU3RyaW5nKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzT3B0aW9uYWxCeXRlcygpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT1BUSU9OQUxfQllURVNfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsQnl0ZXMoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmIChoYXNPcHRpb25hbE1lc3NhZ2UoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMX01FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsTWVzc2FnZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKGhhc09wdGlvbmFsR3JvdXAoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9QVElPTkFMR1JPVVBfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9wdGlvbmFsR3JvdXAoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBTVFJJTkdfU1RSSU5HX01BUF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIHN3aXRjaCAob25lb2ZGaWVsZENhc2VfKSB7CiAgICAgICAgY2FzZSA1MzY4NzAwMTE6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9VSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZVaW50MzIoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNTM2ODcwMDEyOgogICAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgT05FT0ZfVEVTVF9BTExfVFlQRVNfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZUZXN0QWxsVHlwZXMoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1MzY4NzAwMTM6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9TVFJJTkdfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZTdHJpbmcoKS5oYXNoQ29kZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1MzY4NzAwMTQ6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9CWVRFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZkJ5dGVzKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMDoKICAgICAgICBkZWZhdWx0OgogICAgICB9CiAgICAgIGhhc2ggPSBoYXNoRmllbGRzKGhhc2gsIGdldEV4dGVuc2lvbkZpZWxkcygpKTsKICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlQnVpbGRlcjwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSwgQnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgNTM2ODcwMDEwOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDUzNjg3MDAxMDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewogICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwogICAgICAgIG1heWJlRm9yY2VCdWlsZGVySW5pdGlhbGl6YXRpb24oKTsKICAgICAgfQogICAgICBwcml2YXRlIHZvaWQgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpIHsKICAgICAgICBpZiAoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgICAgICAgIC5hbHdheXNVc2VGaWVsZEJ1aWxkZXJzKSB7CiAgICAgICAgICBnZXRPcHRpb25hbE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIG9wdGlvbmFsSW50MzJfID0gMDsKICAgICAgICBmaXhlZDMyXyA9IDA7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBwYWNrZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBvcHRpb25hbEVudW1fID0gNDsKICAgICAgICBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgICAgICBvcHRpb25hbEJ5dGVzXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgICBvcHRpb25hbE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvcHRpb25hbEdyb3VwXyA9IG51bGw7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuY2xlYXIoKTsKICAgICAgICBpZiAob25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgYnVpbGRQYXJ0aWFsT25lb2ZzKHJlc3VsdCk7CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpbnQgdG9fYml0RmllbGQwXyA9IDA7CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEludDMyXyA9IG9wdGlvbmFsSW50MzJfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmZpeGVkMzJfID0gZml4ZWQzMl87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgICByZXBlYXRlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRJbnQzMl8gPSByZXBlYXRlZEludDMyXzsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHBhY2tlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucGFja2VkSW50MzJfID0gcGFja2VkSW50MzJfOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsRW51bV8gPSBvcHRpb25hbEVudW1fOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDIwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsU3RyaW5nXyA9IG9wdGlvbmFsU3RyaW5nXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5vcHRpb25hbEJ5dGVzXyA9IG9wdGlvbmFsQnl0ZXNfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDgwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsTWVzc2FnZV8gPSBvcHRpb25hbE1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsCiAgICAgICAgICAgICAgPyBvcHRpb25hbE1lc3NhZ2VfCiAgICAgICAgICAgICAgOiBvcHRpb25hbE1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMTAwKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm9wdGlvbmFsR3JvdXBfID0gb3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwKICAgICAgICAgICAgICA/IG9wdGlvbmFsR3JvdXBfCiAgICAgICAgICAgICAgOiBvcHRpb25hbEdyb3VwQnVpbGRlcl8uYnVpbGQoKTsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5zdHJpbmdTdHJpbmdNYXBfID0gaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKTsKICAgICAgICAgIHJlc3VsdC5zdHJpbmdTdHJpbmdNYXBfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbE9uZW9mcyhjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUgcmVzdWx0KSB7CiAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRDYXNlXyA9IG9uZW9mRmllbGRDYXNlXzsKICAgICAgICByZXN1bHQub25lb2ZGaWVsZF8gPSB0aGlzLm9uZW9mRmllbGRfOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyICYmCiAgICAgICAgICAgIG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRfID0gb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIHNldEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLCBUeXBlPiBleHRlbnNpb24sCiAgICAgICAgICBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VHlwZT4gQnVpbGRlciBzZXRFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSwgamF2YS51dGlsLkxpc3Q8VHlwZT4+IGV4dGVuc2lvbiwKICAgICAgICAgIGludCBpbmRleCwgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRFeHRlbnNpb24oZXh0ZW5zaW9uLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIGFkZEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgVHlwZSB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRFeHRlbnNpb24oZXh0ZW5zaW9uLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFQ+IEJ1aWxkZXIgY2xlYXJFeHRlbnNpb24oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSwgVD4gZXh0ZW5zaW9uKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRXh0ZW5zaW9uKGV4dGVuc2lvbik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsSW50MzIoKSkgewogICAgICAgICAgc2V0T3B0aW9uYWxJbnQzMihvdGhlci5nZXRPcHRpb25hbEludDMyKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzRml4ZWQzMigpKSB7CiAgICAgICAgICBzZXRGaXhlZDMyKG90aGVyLmdldEZpeGVkMzIoKSk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRJbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICBpZiAocmVwZWF0ZWRJbnQzMl8uaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfID0gb3RoZXIucmVwZWF0ZWRJbnQzMl87CiAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZEludDMyXy5hZGRBbGwob3RoZXIucmVwZWF0ZWRJbnQzMl8pOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghb3RoZXIucGFja2VkSW50MzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgaWYgKHBhY2tlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcGFja2VkSW50MzJfID0gb3RoZXIucGFja2VkSW50MzJfOwogICAgICAgICAgICBwYWNrZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICBwYWNrZWRJbnQzMl8uYWRkQWxsKG90aGVyLnBhY2tlZEludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsRW51bSgpKSB7CiAgICAgICAgICBzZXRPcHRpb25hbEVudW0ob3RoZXIuZ2V0T3B0aW9uYWxFbnVtKCkpOwogICAgICAgIH0KICAgICAgICBpZiAob3RoZXIuaGFzT3B0aW9uYWxTdHJpbmcoKSkgewogICAgICAgICAgb3B0aW9uYWxTdHJpbmdfID0gb3RoZXIub3B0aW9uYWxTdHJpbmdfOwogICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEJ5dGVzKCkpIHsKICAgICAgICAgIHNldE9wdGlvbmFsQnl0ZXMob3RoZXIuZ2V0T3B0aW9uYWxCeXRlcygpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc09wdGlvbmFsTWVzc2FnZSgpKSB7CiAgICAgICAgICBtZXJnZU9wdGlvbmFsTWVzc2FnZShvdGhlci5nZXRPcHRpb25hbE1lc3NhZ2UoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNPcHRpb25hbEdyb3VwKCkpIHsKICAgICAgICAgIG1lcmdlT3B0aW9uYWxHcm91cChvdGhlci5nZXRPcHRpb25hbEdyb3VwKCkpOwogICAgICAgIH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVTdHJpbmdTdHJpbmdNYXAoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICBzd2l0Y2ggKG90aGVyLmdldE9uZW9mRmllbGRDYXNlKCkpIHsKICAgICAgICAgIGNhc2UgT05FT0ZfVUlOVDMyOiB7CiAgICAgICAgICAgIHNldE9uZW9mVWludDMyKG90aGVyLmdldE9uZW9mVWludDMyKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfVEVTVF9BTExfVFlQRVM6IHsKICAgICAgICAgICAgbWVyZ2VPbmVvZlRlc3RBbGxUeXBlcyhvdGhlci5nZXRPbmVvZlRlc3RBbGxUeXBlcygpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX1NUUklORzogewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1MzY4NzAwMTM7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gb3RoZXIub25lb2ZGaWVsZF87CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfQllURVM6IHsKICAgICAgICAgICAgc2V0T25lb2ZCeXRlcyhvdGhlci5nZXRPbmVvZkJ5dGVzKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZGSUVMRF9OT1RfU0VUOiB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlRXh0ZW5zaW9uRmllbGRzKG90aGVyKTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgLTcyOTY6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsSW50MzJfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyOTYKICAgICAgICAgICAgICBjYXNlIC03Mjg4OiB7CiAgICAgICAgICAgICAgICBmaXhlZDMyXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03Mjg4CiAgICAgICAgICAgICAgY2FzZSAtNzI4MDogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzI4MAogICAgICAgICAgICAgIGNhc2UgLTcyNzg6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEludDMyXy5hZGRJbnQoaW5wdXQucmVhZEludDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03Mjc4CiAgICAgICAgICAgICAgY2FzZSAtNzI3MjogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVBhY2tlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgICAgICBwYWNrZWRJbnQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03MjcyCiAgICAgICAgICAgICAgY2FzZSAtNzI3MDogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICBwYWNrZWRJbnQzMl8uYWRkSW50KGlucHV0LnJlYWRJbnQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzI3MAogICAgICAgICAgICAgIGNhc2UgLTcyNjQ6IHsKICAgICAgICAgICAgICAgIGludCB0bXBSYXcgPSBpbnB1dC5yZWFkRW51bSgpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHRtcFZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuZm9yTnVtYmVyKHRtcFJhdyk7CiAgICAgICAgICAgICAgICBpZiAodG1wVmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg1MzY4NzAwMDQsIHRtcFJhdyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBvcHRpb25hbEVudW1fID0gdG1wUmF3OwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyNjQKICAgICAgICAgICAgICBjYXNlIC03MjU0OiB7CiAgICAgICAgICAgICAgICBvcHRpb25hbFN0cmluZ18gPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzI1NAogICAgICAgICAgICAgIGNhc2UgLTcyNDY6IHsKICAgICAgICAgICAgICAgIG9wdGlvbmFsQnl0ZXNfID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyNDYKICAgICAgICAgICAgICBjYXNlIC03MjM4OiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbE1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03MjM4CiAgICAgICAgICAgICAgY2FzZSAtNzIyOTogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZEdyb3VwKDUzNjg3MDAwOCwKICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpLAogICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAtNzIyOQogICAgICAgICAgICAgIGNhc2UgLTcyMTQ6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgICAgICAgICAgICAgIHN0cmluZ1N0cmluZ01hcF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgU3RyaW5nU3RyaW5nTWFwRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgc3RyaW5nU3RyaW5nTWFwX18uZ2V0S2V5KCksIHN0cmluZ1N0cmluZ01hcF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03MjE0CiAgICAgICAgICAgICAgY2FzZSAtNzIwODogewogICAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBpbnB1dC5yZWFkVUludDMyKCk7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1MzY4NzAwMTE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcyMDgKICAgICAgICAgICAgICBjYXNlIC03MTk4OiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPbmVvZlRlc3RBbGxUeXBlc0ZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1MzY4NzAwMTI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcxOTgKICAgICAgICAgICAgICBjYXNlIC03MTkwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDUzNjg3MDAxMzsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYnM7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgLTcxOTAKICAgICAgICAgICAgICBjYXNlIC03MTgyOiB7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDE0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIC03MTgyCiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgcHJpdmF0ZSBqYXZhLmxhbmcuT2JqZWN0IG9uZW9mRmllbGRfOwogICAgICBwdWJsaWMgT25lb2ZGaWVsZENhc2UKICAgICAgICAgIGdldE9uZW9mRmllbGRDYXNlKCkgewogICAgICAgIHJldHVybiBPbmVvZkZpZWxkQ2FzZS5mb3JOdW1iZXIoCiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZGaWVsZCgpIHsKICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IG9wdGlvbmFsSW50MzJfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gNTM2ODcwMDAwOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbEludDMyIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxJbnQzMigpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIG9wdGlvbmFsX2ludDMyID0gNTM2ODcwMDAwOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxJbnQzMi4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRPcHRpb25hbEludDMyKCkgewogICAgICAgIHJldHVybiBvcHRpb25hbEludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSA1MzY4NzAwMDA7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsSW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBvcHRpb25hbEludDMyXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgb3B0aW9uYWxfaW50MzIgPSA1MzY4NzAwMDA7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsSW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIG9wdGlvbmFsSW50MzJfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgZml4ZWQzMl8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZml4ZWRfMzIgPSA1MzY4NzAwMDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGZpeGVkMzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNGaXhlZDMyKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgZml4ZWRfMzIgPSA1MzY4NzAwMDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBmaXhlZDMyLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEZpeGVkMzIoKSB7CiAgICAgICAgcmV0dXJuIGZpeGVkMzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBmaXhlZF8zMiA9IDUzNjg3MDAwMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgZml4ZWQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpeGVkMzIoaW50IHZhbHVlKSB7CgogICAgICAgIGZpeGVkMzJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBmaXhlZF8zMiA9IDUzNjg3MDAwMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRml4ZWQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgZml4ZWQzMl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkSW50MzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZEludDMyXyA9IG1ha2VNdXRhYmxlQ29weShyZXBlYXRlZEludDMyXyk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSA1MzY4NzAwMDIgW3BhY2tlZCA9IGZhbHNlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkSW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRSZXBlYXRlZEludDMyTGlzdCgpIHsKICAgICAgICByZXBlYXRlZEludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEludDMyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50MzIoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfLmdldEludChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRJbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkSW50MzIoCiAgICAgICAgICBpbnQgaW5kZXgsIGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRJbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDUzNjg3MDAwMiBbcGFja2VkID0gZmFsc2VdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlcyBUaGUgcmVwZWF0ZWRJbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkSW50MzIoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2VMaXRlLkJ1aWxkZXIuYWRkQWxsKAogICAgICAgICAgICB2YWx1ZXMsIHJlcGVhdGVkSW50MzJfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gNTM2ODcwMDAyIFtwYWNrZWQgPSBmYWxzZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkSW50MzIoKSB7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHBhY2tlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICBwcml2YXRlIHZvaWQgZW5zdXJlUGFja2VkSW50MzJJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFwYWNrZWRJbnQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHBhY2tlZEludDMyXyA9IG1ha2VNdXRhYmxlQ29weShwYWNrZWRJbnQzMl8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDUzNjg3MDAwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSBwYWNrZWRJbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFBhY2tlZEludDMyTGlzdCgpIHsKICAgICAgICBwYWNrZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiBwYWNrZWRJbnQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHBhY2tlZF9pbnQzMiA9IDUzNjg3MDAwMyBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiBwYWNrZWRJbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UGFja2VkSW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcGFja2VkSW50MzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSBwYWNrZWRJbnQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFBhY2tlZEludDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiBwYWNrZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRJbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFBhY2tlZEludDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUGFja2VkSW50MzJJc011dGFibGUoKTsKICAgICAgICBwYWNrZWRJbnQzMl8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiBwYWNrZWRfaW50MzIgPSA1MzY4NzAwMDMgW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYWNrZWRJbnQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFBhY2tlZEludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHBhY2tlZEludDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHBhY2tlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUGFja2VkSW50MzIoCiAgICAgICAgICBqYXZhLmxhbmcuSXRlcmFibGU8PyBleHRlbmRzIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBlbnN1cmVQYWNrZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCBwYWNrZWRJbnQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcGFja2VkX2ludDMyID0gNTM2ODcwMDAzIFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGFja2VkSW50MzIoKSB7CiAgICAgICAgcGFja2VkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDgpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBvcHRpb25hbEVudW1fID0gNDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGUgb3B0aW9uYWxfZW51bSA9IDUzNjg3MDAwNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb3B0aW9uYWxFbnVtIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxFbnVtKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDEwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9lbnVtID0gNTM2ODcwMDA0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxFbnVtLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIGdldE9wdGlvbmFsRW51bSgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUgcmVzdWx0ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmZvck51bWJlcihvcHRpb25hbEVudW1fKTsKICAgICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuRk9SRUlHTl9MSVRFX0ZPTyA6IHJlc3VsdDsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZSBvcHRpb25hbF9lbnVtID0gNTM2ODcwMDA0OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvcHRpb25hbEVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbEVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgb3B0aW9uYWxFbnVtXyA9IHZhbHVlLmdldE51bWJlcigpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlIG9wdGlvbmFsX2VudW0gPSA1MzY4NzAwMDQ7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsRW51bSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgb3B0aW9uYWxFbnVtXyA9IDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgamF2YS5sYW5nLk9iamVjdCBvcHRpb25hbFN0cmluZ18gPSAiIjsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09wdGlvbmFsU3RyaW5nKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDIwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9wdGlvbmFsU3RyaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T3B0aW9uYWxTdHJpbmcoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ187CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICBvcHRpb25hbFN0cmluZ18gPSBzOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgc3RyaW5nIG9wdGlvbmFsX3N0cmluZyA9IDUzNjg3MDAwNTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvcHRpb25hbFN0cmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldE9wdGlvbmFsU3RyaW5nQnl0ZXMoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSBvcHRpb25hbFN0cmluZ187CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGI7CiAgICAgICAgICByZXR1cm4gYjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9wdGlvbmFsU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T3B0aW9uYWxTdHJpbmcoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbFN0cmluZ18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIHN0cmluZyBvcHRpb25hbF9zdHJpbmcgPSA1MzY4NzAwMDU7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsU3RyaW5nKCkgewogICAgICAgIG9wdGlvbmFsU3RyaW5nXyA9IGdldERlZmF1bHRJbnN0YW5jZSgpLmdldE9wdGlvbmFsU3RyaW5nKCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMjApOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBzdHJpbmcgb3B0aW9uYWxfc3RyaW5nID0gNTM2ODcwMDA1OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBieXRlcyBmb3Igb3B0aW9uYWxTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbFN0cmluZ0J5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbFN0cmluZ18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIG9wdGlvbmFsQnl0ZXNfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSA1MzY4NzAwMDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPcHRpb25hbEJ5dGVzKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDQwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSA1MzY4NzAwMDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvcHRpb25hbEJ5dGVzLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9wdGlvbmFsQnl0ZXMoKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbmFsQnl0ZXNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBvcHRpb25hbF9ieXRlcyA9IDUzNjg3MDAwNjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb3B0aW9uYWxCeXRlcyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsQnl0ZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvcHRpb25hbEJ5dGVzXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgb3B0aW9uYWxfYnl0ZXMgPSA1MzY4NzAwMDY7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9wdGlvbmFsQnl0ZXMoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwNDApOwogICAgICAgIG9wdGlvbmFsQnl0ZXNfID0gZ2V0RGVmYXVsdEluc3RhbmNlKCkuZ2V0T3B0aW9uYWxCeXRlcygpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbE1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+IG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvcHRpb25hbE1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxNZXNzYWdlKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDgwKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxNZXNzYWdlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRPcHRpb25hbE1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE1lc3NhZ2VfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiBvcHRpb25hbE1lc3NhZ2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8uZ2V0TWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsTWVzc2FnZShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvcHRpb25hbE1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUgb3B0aW9uYWxfbWVzc2FnZSA9IDUzNjg3MDAwNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPcHRpb25hbE1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlXyA9IGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25hbE1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VPcHRpb25hbE1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIHZhbHVlKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDgwKSAhPSAwKSAmJgogICAgICAgICAgICBvcHRpb25hbE1lc3NhZ2VfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxNZXNzYWdlXyAhPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxNZXNzYWdlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcHRpb25hbE1lc3NhZ2VfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbE1lc3NhZ2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxNZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDgwKTsKICAgICAgICBvcHRpb25hbE1lc3NhZ2VfID0gbnVsbDsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSBvcHRpb25hbF9tZXNzYWdlID0gNTM2ODcwMDA3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciBnZXRPcHRpb25hbE1lc3NhZ2VCdWlsZGVyKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gZ2V0T3B0aW9uYWxNZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciBnZXRPcHRpb25hbE1lc3NhZ2VPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsTWVzc2FnZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbE1lc3NhZ2VfID09IG51bGwgPwogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsTWVzc2FnZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlIG9wdGlvbmFsX21lc3NhZ2UgPSA1MzY4NzAwMDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsTWVzc2FnZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAob3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbE1lc3NhZ2UoKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9wdGlvbmFsTWVzc2FnZV8gPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gb3B0aW9uYWxNZXNzYWdlQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgb3B0aW9uYWxHcm91cF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlcj4gb3B0aW9uYWxHcm91cEJ1aWxkZXJfOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDUzNjg3MDAwOCB7IC4uLiB9PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9wdGlvbmFsZ3JvdXAgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT3B0aW9uYWxHcm91cCgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb3B0aW9uYWxncm91cC4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCBnZXRPcHRpb25hbEdyb3VwKCkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBfID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsR3JvdXAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAgdmFsdWUpIHsKICAgICAgICBpZiAob3B0aW9uYWxHcm91cEJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9wdGlvbmFsR3JvdXAoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSBidWlsZGVyRm9yVmFsdWUuYnVpbGQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLnNldE1lc3NhZ2UoYnVpbGRlckZvclZhbHVlLmJ1aWxkKCkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT3B0aW9uYWxHcm91cChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCB2YWx1ZSkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAxMDApICE9IDApICYmCiAgICAgICAgICAgIG9wdGlvbmFsR3JvdXBfICE9IG51bGwgJiYKICAgICAgICAgICAgb3B0aW9uYWxHcm91cF8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgZ2V0T3B0aW9uYWxHcm91cEJ1aWxkZXIoKS5tZXJnZUZyb20odmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb3B0aW9uYWxHcm91cF8gPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChvcHRpb25hbEdyb3VwXyAhPSBudWxsKSB7CiAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT3B0aW9uYWxHcm91cCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDEwMCk7CiAgICAgICAgb3B0aW9uYWxHcm91cF8gPSBudWxsOwogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgb3B0aW9uYWxHcm91cEJ1aWxkZXJfLmRpc3Bvc2UoKTsKICAgICAgICAgIG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBncm91cCBPcHRpb25hbEdyb3VwID0gNTM2ODcwMDA4IHsgLi4uIH08L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciBnZXRPcHRpb25hbEdyb3VwQnVpbGRlcigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGdyb3VwIE9wdGlvbmFsR3JvdXAgPSA1MzY4NzAwMDggeyAuLi4gfTwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cE9yQnVpbGRlciBnZXRPcHRpb25hbEdyb3VwT3JCdWlsZGVyKCkgewogICAgICAgIGlmIChvcHRpb25hbEdyb3VwQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG9wdGlvbmFsR3JvdXBCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwXyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cC5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IG9wdGlvbmFsR3JvdXBfOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgZ3JvdXAgT3B0aW9uYWxHcm91cCA9IDUzNjg3MDAwOCB7IC4uLiB9PC9jb2RlPgogICAgICAgKi8KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZS5PcHRpb25hbEdyb3VwT3JCdWlsZGVyPiAKICAgICAgICAgIGdldE9wdGlvbmFsR3JvdXBGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9wdGlvbmFsR3JvdXBCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBvcHRpb25hbEdyb3VwQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0aW9uYWxHcm91cCwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXAuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlLk9wdGlvbmFsR3JvdXBPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbEdyb3VwKCksCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvcHRpb25hbEdyb3VwXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBvcHRpb25hbEdyb3VwQnVpbGRlcl87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IHN0cmluZ1N0cmluZ01hcF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgICAgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKSB7CiAgICAgICAgaWYgKHN0cmluZ1N0cmluZ01hcF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBTdHJpbmdTdHJpbmdNYXBEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHN0cmluZ1N0cmluZ01hcF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVTdHJpbmdTdHJpbmdNYXAoKSB7CiAgICAgICAgaWYgKHN0cmluZ1N0cmluZ01hcF8gPT0gbnVsbCkgewogICAgICAgICAgc3RyaW5nU3RyaW5nTWFwXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgU3RyaW5nU3RyaW5nTWFwRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghc3RyaW5nU3RyaW5nTWFwXy5pc011dGFibGUoKSkgewogICAgICAgICAgc3RyaW5nU3RyaW5nTWFwXyA9IHN0cmluZ1N0cmluZ01hcF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHN0cmluZ1N0cmluZ01hcF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRTdHJpbmdTdHJpbmdNYXBDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgc3RyaW5nX3N0cmluZ19tYXAgPSA1MzY4NzAwMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc1N0cmluZ1N0cmluZ01hcCgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0U3RyaW5nU3RyaW5nTWFwTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBnZXRTdHJpbmdTdHJpbmdNYXAoKSB7CiAgICAgICAgcmV0dXJuIGdldFN0cmluZ1N0cmluZ01hcE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0U3RyaW5nU3RyaW5nTWFwTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldFN0cmluZ1N0cmluZ01hcCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZ2V0U3RyaW5nU3RyaW5nTWFwT3JEZWZhdWx0KAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRTdHJpbmdTdHJpbmdNYXAoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgc3RyaW5nX3N0cmluZ19tYXAgPSA1MzY4NzAwMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRTdHJpbmdTdHJpbmdNYXBPclRocm93KAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0U3RyaW5nU3RyaW5nTWFwKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDIwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVN0cmluZ1N0cmluZ01hcCgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgICAgZ2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZVN0cmluZ1N0cmluZ01hcCgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBzdHJpbmdfc3RyaW5nX21hcCA9IDUzNjg3MDAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRTdHJpbmdTdHJpbmdNYXAoCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSwKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCB2YWx1ZSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IHN0cmluZ19zdHJpbmdfbWFwID0gNTM2ODcwMDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbFN0cmluZ1N0cmluZ01hcCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlU3RyaW5nU3RyaW5nTWFwKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gNTM2ODcwMDExOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlVpbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlVpbnQzMigpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+dWludDMyIG9uZW9mX3VpbnQzMiA9IDUzNjg3MDAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mVWludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRPbmVvZlVpbnQzMigpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMSkgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIHJldHVybiAwOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT51aW50MzIgb25lb2ZfdWludDMyID0gNTM2ODcwMDExOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvbmVvZlVpbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mVWludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1MzY4NzAwMTE7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+dWludDMyIG9uZW9mX3VpbnQzMiA9IDUzNjg3MDAxMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZVaW50MzIoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTEpIHsKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4gb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlRlc3RBbGxUeXBlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mVGVzdEFsbFR5cGVzKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mVGVzdEFsbFR5cGVzLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRPbmVvZlRlc3RBbGxUeXBlcygpIHsKICAgICAgICBpZiAob25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMikgewogICAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgICAgIHJldHVybiBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZUZXN0QWxsVHlwZXMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmIChvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1MzY4NzAwMTI7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mVGVzdEFsbFR5cGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGJ1aWxkZXJGb3JWYWx1ZSkgewogICAgICAgIGlmIChvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9uZW9mRmllbGRfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDEyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZU9uZW9mVGVzdEFsbFR5cGVzKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMiAmJgogICAgICAgICAgICAgIG9uZW9mRmllbGRfICE9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLm5ld0J1aWxkZXIoKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfKQogICAgICAgICAgICAgICAgLm1lcmdlRnJvbSh2YWx1ZSkuYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSB7CiAgICAgICAgICAgIG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDUzNjg3MDAxMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2ZfdGVzdF9hbGxfdHlwZXMgPSA1MzY4NzAwMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlRlc3RBbGxUeXBlcygpIHsKICAgICAgICBpZiAob25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMikgewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMikgewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfLmNsZWFyKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyIGdldE9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0T25lb2ZUZXN0QWxsVHlwZXNGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3Rlc3RfYWxsX3R5cGVzID0gNTM2ODcwMDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T25lb2ZUZXN0QWxsVHlwZXNPckJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEyKSAmJiAob25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyAhPSBudWxsKSkgewogICAgICAgICAgcmV0dXJuIG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8uZ2V0TWVzc2FnZU9yQnVpbGRlcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMikgewogICAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl90ZXN0X2FsbF90eXBlcyA9IDUzNjg3MDAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T25lb2ZUZXN0QWxsVHlwZXNGaWVsZEJ1aWxkZXIoKSB7CiAgICAgICAgaWYgKG9uZW9mVGVzdEFsbFR5cGVzQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCEob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMikpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZUZXN0QWxsVHlwZXNCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXywKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDEyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBvbmVvZlRlc3RBbGxUeXBlc0J1aWxkZXJfOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdHJpbmcgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlN0cmluZygpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEzKSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMykgewogICAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gczsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEzKSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDEzKSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYjsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN0cmluZygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDUzNjg3MDAxMzsKICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gNTM2ODcwMDEzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlN0cmluZygpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUzNjg3MDAxMykgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDUzNjg3MDAxMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZTdHJpbmdCeXRlcygKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDEzOwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDUzNjg3MDAxNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzKCkgewogICAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDE0OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDUzNjg3MDAxNDs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mQnl0ZXMuCiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXMoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1MzY4NzAwMTQpIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA1MzY4NzAwMTQ7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mQnl0ZXMgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZkJ5dGVzKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTM2ODcwMDE0OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNTM2ODcwMDE0OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkJ5dGVzKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNTM2ODcwMDE0KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RPbmVvZlBhcnNpbmdMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVvZlBhcnNpbmdMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+aW50MzIgb25lb2ZfaW50MzIgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZJbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5pbnQzMiBvbmVvZl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZJbnQzMi4KICAgICAqLwogICAgaW50IGdldE9uZW9mSW50MzIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdWJtZXNzYWdlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZlN1Ym1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2Zfc3VibWVzc2FnZSA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZTdWJtZXNzYWdlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE9uZW9mU3VibWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T25lb2ZTdWJtZXNzYWdlT3JCdWlsZGVyKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZlN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZy4KICAgICAqLwogICAgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmcuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9uZW9mU3RyaW5nQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNCBbZGVmYXVsdCA9ICJkZWZhdWx0IGJ5dGVzIl07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZkJ5dGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNCBbZGVmYXVsdCA9ICJkZWZhdWx0IGJ5dGVzIl07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlcy4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXMoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZTdHJpbmdDb3JkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZ0NvcmQuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmdDb3JkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdDb3JkLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICBnZXRPbmVvZlN0cmluZ0NvcmRCeXRlcygpOwoKICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZCeXRlc0NvcmQoKTsKICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlc0NvcmQuCiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPbmVvZkJ5dGVzQ29yZCgpOwoKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfc3RyaW5nX3BpZWNlID0gNyBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdTdHJpbmdQaWVjZS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZUJ5dGVzKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19zdHJpbmdfcGllY2UgPSA4IFtkZWZhdWx0ID0gImRlZmF1bHQgU3RyaW5nUGllY2UiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZkJ5dGVzU3RyaW5nUGllY2UgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc09uZW9mQnl0ZXNTdHJpbmdQaWVjZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19zdHJpbmdfcGllY2UgPSA4IFtkZWZhdWx0ID0gImRlZmF1bHQgU3RyaW5nUGllY2UiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlc1N0cmluZ1BpZWNlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVjJFbnVtTGl0ZSBvbmVvZl9lbnVtID0gOTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzT25lb2ZFbnVtKCk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5WMkVudW1MaXRlIG9uZW9mX2VudW0gPSA5OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mRW51bS4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSBnZXRPbmVvZkVudW0oKTsKCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZS5PbmVvZkZpZWxkQ2FzZSBnZXRPbmVvZkZpZWxkQ2FzZSgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0T25lb2ZQYXJzaW5nTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RPbmVvZlBhcnNpbmdMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVvZlBhcnNpbmdMaXRlKQogICAgICBUZXN0T25lb2ZQYXJzaW5nTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdE9uZW9mUGFyc2luZ0xpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdE9uZW9mUGFyc2luZ0xpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0T25lb2ZQYXJzaW5nTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0T25lb2ZQYXJzaW5nTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGludCBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGphdmEubGFuZy5PYmplY3Qgb25lb2ZGaWVsZF87CiAgICBwdWJsaWMgZW51bSBPbmVvZkZpZWxkQ2FzZQogICAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZSwKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdE1lc3NhZ2UuSW50ZXJuYWxPbmVPZkVudW0gewogICAgICBPTkVPRl9JTlQzMigxKSwKICAgICAgT05FT0ZfU1VCTUVTU0FHRSgyKSwKICAgICAgT05FT0ZfU1RSSU5HKDMpLAogICAgICBPTkVPRl9CWVRFUyg0KSwKICAgICAgT05FT0ZfU1RSSU5HX0NPUkQoNSksCiAgICAgIE9ORU9GX0JZVEVTX0NPUkQoNiksCiAgICAgIE9ORU9GX1NUUklOR19TVFJJTkdfUElFQ0UoNyksCiAgICAgIE9ORU9GX0JZVEVTX1NUUklOR19QSUVDRSg4KSwKICAgICAgT05FT0ZfRU5VTSg5KSwKICAgICAgT05FT0ZGSUVMRF9OT1RfU0VUKDApOwogICAgICBwcml2YXRlIGZpbmFsIGludCB2YWx1ZTsKICAgICAgcHJpdmF0ZSBPbmVvZkZpZWxkQ2FzZShpbnQgdmFsdWUpIHsKICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtYmVyIG9mIHRoZSBlbnVtIHRvIGxvb2sgZm9yLgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtYmVyLgogICAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgc3RhdGljIE9uZW9mRmllbGRDYXNlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBzdGF0aWMgT25lb2ZGaWVsZENhc2UgZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICAgIGNhc2UgMTogcmV0dXJuIE9ORU9GX0lOVDMyOwogICAgICAgICAgY2FzZSAyOiByZXR1cm4gT05FT0ZfU1VCTUVTU0FHRTsKICAgICAgICAgIGNhc2UgMzogcmV0dXJuIE9ORU9GX1NUUklORzsKICAgICAgICAgIGNhc2UgNDogcmV0dXJuIE9ORU9GX0JZVEVTOwogICAgICAgICAgY2FzZSA1OiByZXR1cm4gT05FT0ZfU1RSSU5HX0NPUkQ7CiAgICAgICAgICBjYXNlIDY6IHJldHVybiBPTkVPRl9CWVRFU19DT1JEOwogICAgICAgICAgY2FzZSA3OiByZXR1cm4gT05FT0ZfU1RSSU5HX1NUUklOR19QSUVDRTsKICAgICAgICAgIGNhc2UgODogcmV0dXJuIE9ORU9GX0JZVEVTX1NUUklOR19QSUVDRTsKICAgICAgICAgIGNhc2UgOTogcmV0dXJuIE9ORU9GX0VOVU07CiAgICAgICAgICBjYXNlIDA6IHJldHVybiBPTkVPRkZJRUxEX05PVF9TRVQ7CiAgICAgICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXROdW1iZXIoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIE9uZW9mRmllbGRDYXNlCiAgICBnZXRPbmVvZkZpZWxkQ2FzZSgpIHsKICAgICAgcmV0dXJuIE9uZW9mRmllbGRDYXNlLmZvck51bWJlcigKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfSU5UMzJfRklFTERfTlVNQkVSID0gMTsKICAgIC8qKgogICAgICogPGNvZGU+aW50MzIgb25lb2ZfaW50MzIgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZJbnQzMiBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mSW50MzIoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gMTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+aW50MzIgb25lb2ZfaW50MzIgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mSW50MzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0T25lb2ZJbnQzMigpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfU1VCTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAyOwogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3VibWVzc2FnZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3VibWVzc2FnZSgpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAyOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN1Ym1lc3NhZ2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE9uZW9mU3VibWVzc2FnZSgpIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAyKSB7CiAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgZ2V0T25lb2ZTdWJtZXNzYWdlT3JCdWlsZGVyKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9TVFJJTkdfRklFTERfTlVNQkVSID0gMzsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDM7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmcgPSAzOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPSAKICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpICYmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMykpIHsKICAgICAgICAgIG9uZW9mRmllbGRfID0gczsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHM7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nLgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IGI7CiAgICAgICAgfQogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9CWVRFU19GSUVMRF9OVU1CRVIgPSA0OwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDQgW2RlZmF1bHQgPSAiZGVmYXVsdCBieXRlcyJdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlcyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mQnl0ZXMoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNDsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA0IFtkZWZhdWx0ID0gImRlZmF1bHQgYnl0ZXMiXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE9uZW9mQnl0ZXMoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNCkgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5ieXRlc0RlZmF1bHRWYWx1ZSgiZGVmYXVsdCBieXRlcyIpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1NUUklOR19DT1JEX0ZJRUxEX05VTUJFUiA9IDU7CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nQ29yZCgpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA1OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX2NvcmQgPSA1IFtkZWZhdWx0ID0gImRlZmF1bHQgQ29yZCIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZTdHJpbmdDb3JkLgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZ0NvcmQoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gImRlZmF1bHQgQ29yZCI7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0gCiAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSAmJiAob25lb2ZGaWVsZENhc2VfID09IDUpKSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdDb3JkLgogICAgICovCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nCiAgICAgICAgZ2V0T25lb2ZTdHJpbmdDb3JkQnl0ZXMoKSB7CiAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gImRlZmF1bHQgQ29yZCI7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICB9CiAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgIChqYXZhLmxhbmcuU3RyaW5nKSByZWYpOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBiOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYjsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfQllURVNfQ09SRF9GSUVMRF9OVU1CRVIgPSA2OwogICAgLyoqCiAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19jb3JkID0gNiBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mQnl0ZXNDb3JkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZCeXRlc0NvcmQoKSB7CiAgICAgIHJldHVybiBvbmVvZkZpZWxkQ2FzZV8gPT0gNjsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgb25lb2ZCeXRlc0NvcmQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlc0NvcmQoKSB7CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNikgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1NUUklOR19TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSID0gNzsKICAgIC8qKgogICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZTdHJpbmdTdHJpbmdQaWVjZSgpIHsKICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA3OwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlLgogICAgICovCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCkgewogICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDcpIHsKICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgfQogICAgICBpZiAocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykgewogICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IAogICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkgJiYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSkgewogICAgICAgICAgb25lb2ZGaWVsZF8gPSBzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gczsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdTdHJpbmdQaWVjZS4KICAgICAqLwogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgIGdldE9uZW9mU3RyaW5nU3RyaW5nUGllY2VCeXRlcygpIHsKICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSB7CiAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYiA9IAogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSB7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IGI7CiAgICAgICAgfQogICAgICAgIHJldHVybiBiOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9CWVRFU19TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSID0gODsKICAgIC8qKgogICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfc3RyaW5nX3BpZWNlID0gOCBbZGVmYXVsdCA9ICJkZWZhdWx0IFN0cmluZ1BpZWNlIiwgY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlc1N0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDg7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzX3N0cmluZ19waWVjZSA9IDggW2RlZmF1bHQgPSAiZGVmYXVsdCBTdHJpbmdQaWVjZSIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzU3RyaW5nUGllY2UuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDgpIHsKICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF87CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuYnl0ZXNEZWZhdWx0VmFsdWUoImRlZmF1bHQgU3RyaW5nUGllY2UiKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9FTlVNX0ZJRUxEX05VTUJFUiA9IDk7CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5WMkVudW1MaXRlIG9uZW9mX2VudW0gPSA5OzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZFbnVtIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZFbnVtKCkgewogICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5WMkVudW1MaXRlIG9uZW9mX2VudW0gPSA5OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIG9uZW9mRW51bS4KICAgICAqLwogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUgZ2V0T25lb2ZFbnVtKCkgewogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuZm9yTnVtYmVyKAogICAgICAgICAgICAoamF2YS5sYW5nLkludGVnZXIpIG9uZW9mRmllbGRfKTsKICAgICAgICByZXR1cm4gcmVzdWx0ID09IG51bGwgPyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlLlYyX0ZJUlNUIDogcmVzdWx0OwogICAgICB9CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlLlYyX0ZJUlNUOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoCiAgICAgICAgICAgIDEsIChpbnQpKChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF8pKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICBvdXRwdXQud3JpdGVNZXNzYWdlKDIsIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMud3JpdGVTdHJpbmcob3V0cHV0LCAzLCBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA0KSB7CiAgICAgICAgb3V0cHV0LndyaXRlQnl0ZXMoCiAgICAgICAgICAgIDQsIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy53cml0ZVN0cmluZyhvdXRwdXQsIDUsIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDYpIHsKICAgICAgICBvdXRwdXQud3JpdGVCeXRlcygKICAgICAgICAgICAgNiwgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNykgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLndyaXRlU3RyaW5nKG91dHB1dCwgNywgb25lb2ZGaWVsZF8pOwogICAgICB9CiAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gOCkgewogICAgICAgIG91dHB1dC53cml0ZUJ5dGVzKAogICAgICAgICAgICA4LCAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXyk7CiAgICAgIH0KICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA5KSB7CiAgICAgICAgb3V0cHV0LndyaXRlRW51bSg5LCAoKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXykpOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDEpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKAogICAgICAgICAgICAgIDEsIChpbnQpKChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF8pKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMiwgKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDMpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmNvbXB1dGVTdHJpbmdTaXplKDMsIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDQpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlQnl0ZXNTaXplKAogICAgICAgICAgICAgIDQsIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmNvbXB1dGVTdHJpbmdTaXplKDUsIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDYpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlQnl0ZXNTaXplKAogICAgICAgICAgICAgIDYsIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDcpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLmNvbXB1dGVTdHJpbmdTaXplKDcsIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDgpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlQnl0ZXNTaXplKAogICAgICAgICAgICAgIDgsIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfKTsKICAgICAgfQogICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlRW51bVNpemUoOSwgKChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF8pKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUpIG9iajsKCiAgICAgIGlmICghZ2V0T25lb2ZGaWVsZENhc2UoKS5lcXVhbHMob3RoZXIuZ2V0T25lb2ZGaWVsZENhc2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgc3dpdGNoIChvbmVvZkZpZWxkQ2FzZV8pIHsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICBpZiAoZ2V0T25lb2ZJbnQzMigpCiAgICAgICAgICAgICAgIT0gb3RoZXIuZ2V0T25lb2ZJbnQzMigpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI6CiAgICAgICAgICBpZiAoIWdldE9uZW9mU3VibWVzc2FnZSgpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZlN1Ym1lc3NhZ2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzoKICAgICAgICAgIGlmICghZ2V0T25lb2ZTdHJpbmcoKQogICAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T25lb2ZTdHJpbmcoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNDoKICAgICAgICAgIGlmICghZ2V0T25lb2ZCeXRlcygpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZkJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDU6CiAgICAgICAgICBpZiAoIWdldE9uZW9mU3RyaW5nQ29yZCgpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZlN0cmluZ0NvcmQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNjoKICAgICAgICAgIGlmICghZ2V0T25lb2ZCeXRlc0NvcmQoKQogICAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0T25lb2ZCeXRlc0NvcmQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNzoKICAgICAgICAgIGlmICghZ2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZSgpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZlN0cmluZ1N0cmluZ1BpZWNlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDg6CiAgICAgICAgICBpZiAoIWdldE9uZW9mQnl0ZXNTdHJpbmdQaWVjZSgpCiAgICAgICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRPbmVvZkJ5dGVzU3RyaW5nUGllY2UoKSkpIHJldHVybiBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgOToKICAgICAgICAgIGlmICghZ2V0T25lb2ZFbnVtKCkKICAgICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldE9uZW9mRW51bSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAwOgogICAgICAgIGRlZmF1bHQ6CiAgICAgIH0KICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBzd2l0Y2ggKG9uZW9mRmllbGRDYXNlXykgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9uZW9mSW50MzIoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX1NVQk1FU1NBR0VfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZTdWJtZXNzYWdlKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzoKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX1NUUklOR19GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZlN0cmluZygpLmhhc2hDb2RlKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDQ6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9CWVRFU19GSUVMRF9OVU1CRVI7CiAgICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRPbmVvZkJ5dGVzKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNToKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX1NUUklOR19DT1JEX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9uZW9mU3RyaW5nQ29yZCgpLmhhc2hDb2RlKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDY6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9CWVRFU19DT1JEX0ZJRUxEX05VTUJFUjsKICAgICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldE9uZW9mQnl0ZXNDb3JkKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNzoKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX1NUUklOR19TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZSgpLmhhc2hDb2RlKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDg6CiAgICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBPTkVPRl9CWVRFU19TVFJJTkdfUElFQ0VfRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkuaGFzaENvZGUoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgOToKICAgICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE9ORU9GX0VOVU1fRklFTERfTlVNQkVSOwogICAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0T25lb2ZFbnVtKCkuZ2V0TnVtYmVyKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDA6CiAgICAgICAgZGVmYXVsdDoKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0T25lb2ZQYXJzaW5nTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVvZlBhcnNpbmdMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE9uZW9mUGFyc2luZ0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmIChvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5jbGVhcigpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RPbmVvZlBhcnNpbmdMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBidWlsZFBhcnRpYWxPbmVvZnMocmVzdWx0KTsKICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWxPbmVvZnMoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgcmVzdWx0KSB7CiAgICAgICAgcmVzdWx0Lm9uZW9mRmllbGRDYXNlXyA9IG9uZW9mRmllbGRDYXNlXzsKICAgICAgICByZXN1bHQub25lb2ZGaWVsZF8gPSB0aGlzLm9uZW9mRmllbGRfOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMiAmJgogICAgICAgICAgICBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZXN1bHQub25lb2ZGaWVsZF8gPSBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgc3dpdGNoIChvdGhlci5nZXRPbmVvZkZpZWxkQ2FzZSgpKSB7CiAgICAgICAgICBjYXNlIE9ORU9GX0lOVDMyOiB7CiAgICAgICAgICAgIHNldE9uZW9mSW50MzIob3RoZXIuZ2V0T25lb2ZJbnQzMigpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX1NVQk1FU1NBR0U6IHsKICAgICAgICAgICAgbWVyZ2VPbmVvZlN1Ym1lc3NhZ2Uob3RoZXIuZ2V0T25lb2ZTdWJtZXNzYWdlKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfU1RSSU5HOiB7CiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDM7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gb3RoZXIub25lb2ZGaWVsZF87CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfQllURVM6IHsKICAgICAgICAgICAgc2V0T25lb2ZCeXRlcyhvdGhlci5nZXRPbmVvZkJ5dGVzKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfU1RSSU5HX0NPUkQ6IHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBvdGhlci5vbmVvZkZpZWxkXzsKICAgICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2FzZSBPTkVPRl9CWVRFU19DT1JEOiB7CiAgICAgICAgICAgIHNldE9uZW9mQnl0ZXNDb3JkKG90aGVyLmdldE9uZW9mQnl0ZXNDb3JkKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfU1RSSU5HX1NUUklOR19QSUVDRTogewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA3OwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG90aGVyLm9uZW9mRmllbGRfOwogICAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9ORU9GX0JZVEVTX1NUUklOR19QSUVDRTogewogICAgICAgICAgICBzZXRPbmVvZkJ5dGVzU3RyaW5nUGllY2Uob3RoZXIuZ2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZfRU5VTTogewogICAgICAgICAgICBzZXRPbmVvZkVudW0ob3RoZXIuZ2V0T25lb2ZFbnVtKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT05FT0ZGSUVMRF9OT1RfU0VUOiB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgKICAgICAgICAgICAgICBjYXNlIDE4OiB7CiAgICAgICAgICAgICAgICBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBnZXRPbmVvZlN1Ym1lc3NhZ2VGaWVsZEJ1aWxkZXIoKS5nZXRCdWlsZGVyKCksCiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxOAogICAgICAgICAgICAgIGNhc2UgMjY6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMzsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYnM7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjYKICAgICAgICAgICAgICBjYXNlIDM0OiB7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAzNAogICAgICAgICAgICAgIGNhc2UgNDI6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYnM7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNDIKICAgICAgICAgICAgICBjYXNlIDUwOiB7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1MAogICAgICAgICAgICAgIGNhc2UgNTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNzsKICAgICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gYnM7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTgKICAgICAgICAgICAgICBjYXNlIDY2OiB7CiAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gODsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA2NgogICAgICAgICAgICAgIGNhc2UgNzI6IHsKICAgICAgICAgICAgICAgIGludCByYXdWYWx1ZSA9IGlucHV0LnJlYWRFbnVtKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHZhbHVlID0KICAgICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlLmZvck51bWJlcihyYXdWYWx1ZSk7CiAgICAgICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25WYXJpbnRGaWVsZCg5LCByYXdWYWx1ZSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA5OwogICAgICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IHJhd1ZhbHVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDcyCiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgcHJpdmF0ZSBqYXZhLmxhbmcuT2JqZWN0IG9uZW9mRmllbGRfOwogICAgICBwdWJsaWMgT25lb2ZGaWVsZENhc2UKICAgICAgICAgIGdldE9uZW9mRmllbGRDYXNlKCkgewogICAgICAgIHJldHVybiBPbmVvZkZpZWxkQ2FzZS5mb3JOdW1iZXIoCiAgICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyk7CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZGaWVsZCgpIHsKICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5pbnQzMiBvbmVvZl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mSW50MzIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZJbnQzMigpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDE7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmludDMyIG9uZW9mX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mSW50MzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldE9uZW9mSW50MzIoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAxKSB7CiAgICAgICAgICByZXR1cm4gKGphdmEubGFuZy5JbnRlZ2VyKSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmludDMyIG9uZW9mX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZJbnQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mSW50MzIoaW50IHZhbHVlKSB7CgogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDE7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+aW50MzIgb25lb2ZfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkludDMyKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMSkgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXzsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBvbmVvZlN1Ym1lc3NhZ2UgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNPbmVvZlN1Ym1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAyOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3VibWVzc2FnZS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0T25lb2ZTdWJtZXNzYWdlKCkgewogICAgICAgIGlmIChvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlKSBvbmVvZkZpZWxkXzsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgICAgcmV0dXJuIG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2Zfc3VibWVzc2FnZSA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZTdWJtZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfLnNldE1lc3NhZ2UodmFsdWUpOwogICAgICAgIH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN1Ym1lc3NhZ2UoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgYnVpbGRlckZvclZhbHVlKSB7CiAgICAgICAgaWYgKG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIG9uZW9mRmllbGRfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8uc2V0TWVzc2FnZShidWlsZGVyRm9yVmFsdWUuYnVpbGQoKSk7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDI7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlT25lb2ZTdWJtZXNzYWdlKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKICAgICAgICBpZiAob25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAyICYmCiAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUubmV3QnVpbGRlcigoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF8pCiAgICAgICAgICAgICAgICAubWVyZ2VGcm9tKHZhbHVlKS5idWlsZFBhcnRpYWwoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAyKSB7CiAgICAgICAgICAgIG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5zZXRNZXNzYWdlKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUgb25lb2Zfc3VibWVzc2FnZSA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZlN1Ym1lc3NhZ2UoKSB7CiAgICAgICAgaWYgKG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMikgewogICAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDIpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8uY2xlYXIoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlIG9uZW9mX3N1Ym1lc3NhZ2UgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgZ2V0T25lb2ZTdWJtZXNzYWdlQnVpbGRlcigpIHsKICAgICAgICByZXR1cm4gZ2V0T25lb2ZTdWJtZXNzYWdlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyIGdldE9uZW9mU3VibWVzc2FnZU9yQnVpbGRlcigpIHsKICAgICAgICBpZiAoKG9uZW9mRmllbGRDYXNlXyA9PSAyKSAmJiAob25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gIT0gbnVsbCkpIHsKICAgICAgICAgIHJldHVybiBvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMikgewogICAgICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIG9uZW9mRmllbGRfOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSBvbmVvZl9zdWJtZXNzYWdlID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0T25lb2ZTdWJtZXNzYWdlRmllbGRCdWlsZGVyKCkgewogICAgICAgIGlmIChvbmVvZlN1Ym1lc3NhZ2VCdWlsZGVyXyA9PSBudWxsKSB7CiAgICAgICAgICBpZiAoIShvbmVvZkZpZWxkQ2FzZV8gPT0gMikpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICAgICAgfQogICAgICAgICAgb25lb2ZTdWJtZXNzYWdlQnVpbGRlcl8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5TaW5nbGVGaWVsZEJ1aWxkZXJWMzwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+KAogICAgICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgb25lb2ZGaWVsZF8sCiAgICAgICAgICAgICAgICAgIGdldFBhcmVudEZvckNoaWxkcmVuKCksCiAgICAgICAgICAgICAgICAgIGlzQ2xlYW4oKSk7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG9uZW9mU3VibWVzc2FnZUJ1aWxkZXJfOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZTdHJpbmcoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSAzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRPbmVvZlN0cmluZygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMykgewogICAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIGlmICghKHJlZiBpbnN0YW5jZW9mIGphdmEubGFuZy5TdHJpbmcpKSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnMgPQogICAgICAgICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgcyA9IGJzLnRvU3RyaW5nVXRmOCgpOwogICAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSAzKSB7CiAgICAgICAgICAgIGlmIChicy5pc1ZhbGlkVXRmOCgpKSB7CiAgICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBzOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChqYXZhLmxhbmcuU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZy4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0T25lb2ZTdHJpbmdCeXRlcygpIHsKICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHJlZiA9ICIiOwogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMykgewogICAgICAgICAgcmVmID0gb25lb2ZGaWVsZF87CiAgICAgICAgfQogICAgICAgIGlmIChyZWYgaW5zdGFuY2VvZiBTdHJpbmcpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBiID0gCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNvcHlGcm9tVXRmOCgKICAgICAgICAgICAgICAgICAgKGphdmEubGFuZy5TdHJpbmcpIHJlZik7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDMpIHsKICAgICAgICAgICAgb25lb2ZGaWVsZF8gPSBiOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nID0gMzs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZTdHJpbmcgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN0cmluZygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDM7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mU3RyaW5nKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gMykgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZyA9IDM7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mU3RyaW5nQnl0ZXMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDM7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNCBbZGVmYXVsdCA9ICJkZWZhdWx0IGJ5dGVzIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mQnl0ZXMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZCeXRlcygpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDQ7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzID0gNCBbZGVmYXVsdCA9ICJkZWZhdWx0IGJ5dGVzIl07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBvbmVvZkJ5dGVzLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPbmVvZkJ5dGVzKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNCkgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5ieXRlc0RlZmF1bHRWYWx1ZSgiZGVmYXVsdCBieXRlcyIpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlcyA9IDQgW2RlZmF1bHQgPSAiZGVmYXVsdCBieXRlcyJdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvbmVvZkJ5dGVzIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZCeXRlcyhjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDQ7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXMgPSA0IFtkZWZhdWx0ID0gImRlZmF1bHQgYnl0ZXMiXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZCeXRlcygpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDQpIHsKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX2NvcmQgPSA1IFtkZWZhdWx0ID0gImRlZmF1bHQgQ29yZCIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mU3RyaW5nQ29yZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nQ29yZCgpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nQ29yZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEubGFuZy5TdHJpbmcgZ2V0T25lb2ZTdHJpbmdDb3JkKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gImRlZmF1bHQgQ29yZCI7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1KSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKCEocmVmIGluc3RhbmNlb2YgamF2YS5sYW5nLlN0cmluZykpIHsKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBicyA9CiAgICAgICAgICAgICAgKGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZykgcmVmOwogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBzID0gYnMudG9TdHJpbmdVdGY4KCk7CiAgICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUpIHsKICAgICAgICAgICAgaWYgKGJzLmlzVmFsaWRVdGY4KCkpIHsKICAgICAgICAgICAgICBvbmVvZkZpZWxkXyA9IHM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKGphdmEubGFuZy5TdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGJ5dGVzIGZvciBvbmVvZlN0cmluZ0NvcmQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcKICAgICAgICAgIGdldE9uZW9mU3RyaW5nQ29yZEJ5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gImRlZmF1bHQgQ29yZCI7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA1KSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNSkgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGI7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gYjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgb25lb2ZTdHJpbmdDb3JkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZTdHJpbmdDb3JkKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOyB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gNTsKICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX2NvcmQgPSA1IFtkZWZhdWx0ID0gImRlZmF1bHQgQ29yZCIsIGN0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mU3RyaW5nQ29yZCgpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDUpIHsKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfY29yZCA9IDUgW2RlZmF1bHQgPSAiZGVmYXVsdCBDb3JkIiwgY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nQ29yZCB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mU3RyaW5nQ29yZEJ5dGVzKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA1OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19jb3JkID0gNiBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlc0NvcmQgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgcHVibGljIGJvb2xlYW4gaGFzT25lb2ZCeXRlc0NvcmQoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA2OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19jb3JkID0gNiBbY3R5cGUgPSBDT1JEXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mQnl0ZXNDb3JkLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRPbmVvZkJ5dGVzQ29yZCgpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDYpIHsKICAgICAgICAgIHJldHVybiAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfY29yZCA9IDYgW2N0eXBlID0gQ09SRF07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mQnl0ZXNDb3JkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZCeXRlc0NvcmQoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7IH0KICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSA2OwogICAgICAgIG9uZW9mRmllbGRfID0gdmFsdWU7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzX2NvcmQgPSA2IFtjdHlwZSA9IENPUkRdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkJ5dGVzQ29yZCgpIHsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDYpIHsKICAgICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDA7CiAgICAgICAgICBvbmVvZkZpZWxkXyA9IG51bGw7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZTdHJpbmdTdHJpbmdQaWVjZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mU3RyaW5nU3RyaW5nUGllY2UoKSB7CiAgICAgICAgcmV0dXJuIG9uZW9mRmllbGRDYXNlXyA9PSA3OwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mU3RyaW5nU3RyaW5nUGllY2UuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE9uZW9mU3RyaW5nU3RyaW5nUGllY2UoKSB7CiAgICAgICAgamF2YS5sYW5nLk9iamVjdCByZWYgPSAiIjsKICAgICAgICBpZiAob25lb2ZGaWVsZENhc2VfID09IDcpIHsKICAgICAgICAgIHJlZiA9IG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBqYXZhLmxhbmcuU3RyaW5nKSkgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJzID0KICAgICAgICAgICAgICAoY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nKSByZWY7CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHMgPSBicy50b1N0cmluZ1V0ZjgoKTsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNykgewogICAgICAgICAgICBpZiAoYnMuaXNWYWxpZFV0ZjgoKSkgewogICAgICAgICAgICAgIG9uZW9mRmllbGRfID0gczsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAoamF2YS5sYW5nLlN0cmluZykgcmVmOwogICAgICAgIH0KICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBieXRlcyBmb3Igb25lb2ZTdHJpbmdTdHJpbmdQaWVjZS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZwogICAgICAgICAgZ2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZUJ5dGVzKCkgewogICAgICAgIGphdmEubGFuZy5PYmplY3QgcmVmID0gIiI7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSB7CiAgICAgICAgICByZWYgPSBvbmVvZkZpZWxkXzsKICAgICAgICB9CiAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGIgPSAKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY29weUZyb21VdGY4KAogICAgICAgICAgICAgICAgICAoamF2YS5sYW5nLlN0cmluZykgcmVmKTsKICAgICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gNykgewogICAgICAgICAgICBvbmVvZkZpZWxkXyA9IGI7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gYjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIHJlZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnN0cmluZyBvbmVvZl9zdHJpbmdfc3RyaW5nX3BpZWNlID0gNyBbY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvbmVvZlN0cmluZ1N0cmluZ1BpZWNlIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0T25lb2ZTdHJpbmdTdHJpbmdQaWVjZSgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDc7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+c3RyaW5nIG9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2UgPSA3IFtjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mU3RyaW5nU3RyaW5nUGllY2UoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA3KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5zdHJpbmcgb25lb2Zfc3RyaW5nX3N0cmluZ19waWVjZSA9IDcgW2N0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYnl0ZXMgZm9yIG9uZW9mU3RyaW5nU3RyaW5nUGllY2UgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZlN0cmluZ1N0cmluZ1BpZWNlQnl0ZXMoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDc7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzX3N0cmluZ19waWVjZSA9IDggW2RlZmF1bHQgPSAiZGVmYXVsdCBTdHJpbmdQaWVjZSIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgb25lb2ZCeXRlc1N0cmluZ1BpZWNlIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mQnl0ZXNTdHJpbmdQaWVjZSgpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDg7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPmJ5dGVzIG9uZW9mX2J5dGVzX3N0cmluZ19waWVjZSA9IDggW2RlZmF1bHQgPSAiZGVmYXVsdCBTdHJpbmdQaWVjZSIsIGN0eXBlID0gU1RSSU5HX1BJRUNFXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIG9uZW9mQnl0ZXNTdHJpbmdQaWVjZS4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0T25lb2ZCeXRlc1N0cmluZ1BpZWNlKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gOCkgewogICAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcpIG9uZW9mRmllbGRfOwogICAgICAgIH0KICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5ieXRlc0RlZmF1bHRWYWx1ZSgiZGVmYXVsdCBTdHJpbmdQaWVjZSIpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5ieXRlcyBvbmVvZl9ieXRlc19zdHJpbmdfcGllY2UgPSA4IFtkZWZhdWx0ID0gImRlZmF1bHQgU3RyaW5nUGllY2UiLCBjdHlwZSA9IFNUUklOR19QSUVDRV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG9uZW9mQnl0ZXNTdHJpbmdQaWVjZSB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldE9uZW9mQnl0ZXNTdHJpbmdQaWVjZShjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIG9uZW9mRmllbGRDYXNlXyA9IDg7CiAgICAgICAgb25lb2ZGaWVsZF8gPSB2YWx1ZTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+Ynl0ZXMgb25lb2ZfYnl0ZXNfc3RyaW5nX3BpZWNlID0gOCBbZGVmYXVsdCA9ICJkZWZhdWx0IFN0cmluZ1BpZWNlIiwgY3R5cGUgPSBTVFJJTkdfUElFQ0VdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZkJ5dGVzU3RyaW5nUGllY2UoKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA4KSB7CiAgICAgICAgICBvbmVvZkZpZWxkQ2FzZV8gPSAwOwogICAgICAgICAgb25lb2ZGaWVsZF8gPSBudWxsOwogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICAvKioKICAgICAgICogPGNvZGU+LnByb3RvYnVmX3VuaXR0ZXN0LlYyRW51bUxpdGUgb25lb2ZfZW51bSA9IDk7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIG9uZW9mRW51bSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc09uZW9mRW51bSgpIHsKICAgICAgICByZXR1cm4gb25lb2ZGaWVsZENhc2VfID09IDk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5WMkVudW1MaXRlIG9uZW9mX2VudW0gPSA5OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgb25lb2ZFbnVtLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSBnZXRPbmVvZkVudW0oKSB7CiAgICAgICAgaWYgKG9uZW9mRmllbGRDYXNlXyA9PSA5KSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5WMkVudW1MaXRlIHJlc3VsdCA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuZm9yTnVtYmVyKAogICAgICAgICAgICAgIChqYXZhLmxhbmcuSW50ZWdlcikgb25lb2ZGaWVsZF8pOwogICAgICAgICAgcmV0dXJuIHJlc3VsdCA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZS5WMl9GSVJTVCA6IHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlYyRW51bUxpdGUuVjJfRklSU1Q7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPi5wcm90b2J1Zl91bml0dGVzdC5WMkVudW1MaXRlIG9uZW9mX2VudW0gPSA5OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBvbmVvZkVudW0gdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRPbmVvZkVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVjJFbnVtTGl0ZSB2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gOTsKICAgICAgICBvbmVvZkZpZWxkXyA9IHZhbHVlLmdldE51bWJlcigpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT4ucHJvdG9idWZfdW5pdHRlc3QuVjJFbnVtTGl0ZSBvbmVvZl9lbnVtID0gOTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2ZFbnVtKCkgewogICAgICAgIGlmIChvbmVvZkZpZWxkQ2FzZV8gPT0gOSkgewogICAgICAgICAgb25lb2ZGaWVsZENhc2VfID0gMDsKICAgICAgICAgIG9uZW9mRmllbGRfID0gbnVsbDsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0T25lb2ZQYXJzaW5nTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mUGFyc2luZ0xpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0T25lb2ZQYXJzaW5nTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE9uZW9mUGFyc2luZ0xpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0T25lb2ZQYXJzaW5nTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0T25lb2ZQYXJzaW5nTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RPbmVvZlBhcnNpbmdMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE9uZW9mUGFyc2luZ0xpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE9uZW9mUGFyc2luZ0xpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RPbmVvZlBhcnNpbmdMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdE1lc3NhZ2VTZXRMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNZXNzYWdlU2V0TGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuCiAgICAgICAgICBFeHRlbmRhYmxlTWVzc2FnZU9yQnVpbGRlcjxUZXN0TWVzc2FnZVNldExpdGU+IHsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lc3NhZ2VTZXRMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdE1lc3NhZ2VTZXRMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZU1lc3NhZ2U8CiAgICAgICAgVGVzdE1lc3NhZ2VTZXRMaXRlPiBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lc3NhZ2VTZXRMaXRlKQogICAgICBUZXN0TWVzc2FnZVNldExpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RNZXNzYWdlU2V0TGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0TWVzc2FnZVNldExpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRXh0ZW5kYWJsZUJ1aWxkZXI8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlLCA/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0TWVzc2FnZVNldExpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdE1lc3NhZ2VTZXRMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlU2V0TGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZVNldExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBpZiAoIWV4dGVuc2lvbnNBcmVJbml0aWFsaXplZCgpKSB7CiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5FeHRlbmRhYmxlTWVzc2FnZTxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGU+LkV4dGVuc2lvbldyaXRlcgogICAgICAgICAgZXh0ZW5zaW9uV3JpdGVyID0gbmV3TWVzc2FnZVNldEV4dGVuc2lvbldyaXRlcigpOwogICAgICBleHRlbnNpb25Xcml0ZXIud3JpdGVVbnRpbCgyMTQ3NDgzNjQ3LCBvdXRwdXQpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVBc01lc3NhZ2VTZXRUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgc2l6ZSArPSBleHRlbnNpb25zU2VyaWFsaXplZFNpemVBc01lc3NhZ2VTZXQoKTsKICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemVBc01lc3NhZ2VTZXQoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlKSBvYmo7CgogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldEV4dGVuc2lvbkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRFeHRlbnNpb25GaWVsZHMoKSkpCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGhhc2ggPSBoYXNoRmllbGRzKGhhc2gsIGdldEV4dGVuc2lvbkZpZWxkcygpKTsKICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNZXNzYWdlU2V0TGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5FeHRlbmRhYmxlQnVpbGRlcjwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSwgQnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lc3NhZ2VTZXRMaXRlKQogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VTZXRMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZVNldExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VTZXRMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlKHRoaXMpOwogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgc2V0RXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUsIFR5cGU+IGV4dGVuc2lvbiwKICAgICAgICAgIFR5cGUgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RXh0ZW5zaW9uKGV4dGVuc2lvbiwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIDxUeXBlPiBCdWlsZGVyIHNldEV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlLCBqYXZhLnV0aWwuTGlzdDxUeXBlPj4gZXh0ZW5zaW9uLAogICAgICAgICAgaW50IGluZGV4LCBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEV4dGVuc2lvbihleHRlbnNpb24sIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgPFR5cGU+IEJ1aWxkZXIgYWRkRXh0ZW5zaW9uKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUsIGphdmEudXRpbC5MaXN0PFR5cGU+PiBleHRlbnNpb24sCiAgICAgICAgICBUeXBlIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZEV4dGVuc2lvbihleHRlbnNpb24sIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyA8VD4gQnVpbGRlciBjbGVhckV4dGVuc2lvbigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlLCBUPiBleHRlbnNpb24pIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJFeHRlbnNpb24oZXh0ZW5zaW9uKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0TWVzc2FnZVNldExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICB0aGlzLm1lcmdlRXh0ZW5zaW9uRmllbGRzKG90aGVyKTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFleHRlbnNpb25zQXJlSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNZXNzYWdlU2V0TGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lc3NhZ2VTZXRMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdE1lc3NhZ2VTZXRMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE1lc3NhZ2VTZXRMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RNZXNzYWdlU2V0TGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RNZXNzYWdlU2V0TGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RNZXNzYWdlU2V0TGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWVzc2FnZVNldExpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RNZXNzYWdlU2V0TGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFBhY2tlZEludDMyT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlBhY2tlZEludDMyKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEludDMyLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkSW50MzIoaW50IGluZGV4KTsKICB9CiAgLyoqCiAgICogPHByZT4KICAgKiBUaGUgZm9sbG93aW5nIGZvdXIgbWVzc2FnZXMgYXJlIHNldCB1cCB0byB0ZXN0IGZvciB3aXJlIGNvbXBhdGliaWxpdHkgYmV0d2VlbgogICAqIHBhY2tlZCBhbmQgbm9uLXBhY2tlZCByZXBlYXRlZCBmaWVsZHMuIFdlIHVzZSB0aGUgZmllbGQgbnVtYmVyIDIwNDgsIGJlY2F1c2UKICAgKiB0aGF0IGlzIGxhcmdlIGVub3VnaCB0byByZXF1aXJlIGEgMy1ieXRlIHZhcmludCBmb3IgdGhlIHRhZy4KICAgKiA8L3ByZT4KICAgKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlBhY2tlZEludDMyfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgUGFja2VkSW50MzIgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuUGFja2VkSW50MzIpCiAgICAgIFBhY2tlZEludDMyT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBQYWNrZWRJbnQzMi5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBQYWNrZWRJbnQzMihjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFBhY2tlZEludDMyKCkgewogICAgICByZXBlYXRlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFBhY2tlZEludDMyKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1BhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1BhY2tlZEludDMyX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDIwNDg7CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkSW50MzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEludDMyLgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50MzJDb3VudCgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkSW50MzIoaW50IGluZGV4KSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQogICAgcHJpdmF0ZSBpbnQgcmVwZWF0ZWRJbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEludDMyTGlzdCgpLnNpemUoKSA+IDApIHsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZygxNjM4Nik7CiAgICAgICAgb3V0cHV0LndyaXRlVUludDMyTm9UYWcocmVwZWF0ZWRJbnQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMk5vVGFnKHJlcGVhdGVkSW50MzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICAgIGRhdGFTaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemVOb1RhZyhyZXBlYXRlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICAgIH0KICAgICAgICBzaXplICs9IGRhdGFTaXplOwogICAgICAgIGlmICghZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5pc0VtcHR5KCkpIHsKICAgICAgICAgIHNpemUgKz0gMzsKICAgICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcoZGF0YVNpemUpOwogICAgICAgIH0KICAgICAgICByZXBlYXRlZEludDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBvdGhlciA9IChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMikgb2JqOwoKICAgICAgaWYgKCFnZXRSZXBlYXRlZEludDMyTGlzdCgpCiAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFJlcGVhdGVkSW50MzJMaXN0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGdldFJlcGVhdGVkSW50MzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZXBlYXRlZEludDMyTGlzdCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogPHByZT4KICAgICAqIFRoZSBmb2xsb3dpbmcgZm91ciBtZXNzYWdlcyBhcmUgc2V0IHVwIHRvIHRlc3QgZm9yIHdpcmUgY29tcGF0aWJpbGl0eSBiZXR3ZWVuCiAgICAgKiBwYWNrZWQgYW5kIG5vbi1wYWNrZWQgcmVwZWF0ZWQgZmllbGRzLiBXZSB1c2UgdGhlIGZpZWxkIG51bWJlciAyMDQ4LCBiZWNhdXNlCiAgICAgKiB0aGF0IGlzIGxhcmdlIGVub3VnaCB0byByZXF1aXJlIGEgMy1ieXRlIHZhcmludCBmb3IgdGhlIHRhZy4KICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlBhY2tlZEludDMyfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuUGFja2VkSW50MzIpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzJPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1BhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9QYWNrZWRJbnQzMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMi5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1BhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEludDMyXyA9IHJlcGVhdGVkSW50MzJfOwogICAgICAgIH0KICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMilvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMi5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBvdGhlci5yZXBlYXRlZEludDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZEludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAxNjM4NDogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjM4NAogICAgICAgICAgICAgIGNhc2UgMTYzODY6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEludDMyXy5hZGRJbnQoaW5wdXQucmVhZEludDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2Mzg2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRJbnQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW50MzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkSW50MzJfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldFJlcGVhdGVkSW50MzJMaXN0KCkgewogICAgICAgIHJlcGVhdGVkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIHJlcGVhdGVkSW50MzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gc2V0IHRoZSB2YWx1ZSBhdC4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEludDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRJbnQzMigKICAgICAgICAgIGludCBpbmRleCwgaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEludDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkSW50MzIgdG8gYWRkLgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEludDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8uYWRkSW50KHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRJbnQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRJbnQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUmVwZWF0ZWRJbnQzMigpIHsKICAgICAgICByZXBlYXRlZEludDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5QYWNrZWRJbnQzMikKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuUGFja2VkSW50MzIpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMiBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRJbnQzMigpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkSW50MzIgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxQYWNrZWRJbnQzMj4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxQYWNrZWRJbnQzMj4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFBhY2tlZEludDMyIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UGFja2VkSW50MzI+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UGFja2VkSW50MzI+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEludDMyIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgTm9uUGFja2VkSW50MzJPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuTm9uUGFja2VkSW50MzIpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRJbnQzMi4KICAgICAqLwogICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+IGdldFJlcGVhdGVkSW50MzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEludDMyLgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkSW50MzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRJbnQzMihpbnQgaW5kZXgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5Ob25QYWNrZWRJbnQzMn0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIE5vblBhY2tlZEludDMyIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0Lk5vblBhY2tlZEludDMyKQogICAgICBOb25QYWNrZWRJbnQzMk9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgTm9uUGFja2VkSW50MzIubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgTm9uUGFja2VkSW50MzIoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBOb25QYWNrZWRJbnQzMigpIHsKICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBOb25QYWNrZWRJbnQzMigpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Ob25QYWNrZWRJbnQzMl9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Ob25QYWNrZWRJbnQzMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMi5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9JTlQzMl9GSUVMRF9OVU1CRVIgPSAyMDQ4OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEludDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEludDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkSW50MzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgcHVibGljIGludCBnZXRSZXBlYXRlZEludDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVwZWF0ZWRJbnQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigyMDQ4LCByZXBlYXRlZEludDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkSW50MzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICBkYXRhU2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplTm9UYWcocmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGkpKTsKICAgICAgICB9CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDMgKiBnZXRSZXBlYXRlZEludDMyTGlzdCgpLnNpemUoKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMikpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIpIG9iajsKCiAgICAgIGlmICghZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKQogICAgICAgICAgLmVxdWFscyhvdGhlci5nZXRSZXBlYXRlZEludDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEludDMyQ291bnQoKSA+IDApIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRVBFQVRFRF9JTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0Lk5vblBhY2tlZEludDMyfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuTm9uUGFja2VkSW50MzIpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzJPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Ob25QYWNrZWRJbnQzMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMi5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMi5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICAgIHJlc3VsdC5yZXBlYXRlZEludDMyXyA9IHJlcGVhdGVkSW50MzJfOwogICAgICAgIH0KICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMilvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMi5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKCFvdGhlci5yZXBlYXRlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEludDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8gPSBvdGhlci5yZXBlYXRlZEludDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCk7CiAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZEludDMyXyk7CiAgICAgICAgICB9CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAxNjM4NDogewogICAgICAgICAgICAgICAgaW50IHYgPSBpbnB1dC5yZWFkSW50MzIoKTsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludCh2KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjM4NAogICAgICAgICAgICAgIGNhc2UgMTYzODY6IHsKICAgICAgICAgICAgICAgIGludCBsZW5ndGggPSBpbnB1dC5yZWFkUmF3VmFyaW50MzIoKTsKICAgICAgICAgICAgICAgIGludCBsaW1pdCA9IGlucHV0LnB1c2hMaW1pdChsZW5ndGgpOwogICAgICAgICAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEludDMyXy5hZGRJbnQoaW5wdXQucmVhZEludDMyKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaW5wdXQucG9wTGltaXQobGltaXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2Mzg2CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5JbnRMaXN0IHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEludDMySXNNdXRhYmxlKCkgewogICAgICAgIGlmICghcmVwZWF0ZWRJbnQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkSW50MzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkSW50MzJfKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEludDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UmVwZWF0ZWRJbnQzMkxpc3QoKSB7CiAgICAgICAgcmVwZWF0ZWRJbnQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZEludDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRJbnQzMi4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMkNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEludDMyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGludDMyIHJlcGVhdGVkX2ludDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEludDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRJbnQzMihpbnQgaW5kZXgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRJbnQzMl8uZ2V0SW50KGluZGV4KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkSW50MzIgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEludDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkSW50MzJfLnNldEludChpbmRleCwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSByZXBlYXRlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRJbnQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRJbnQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkSW50MzJfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBpbnQzMiByZXBlYXRlZF9pbnQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWVzIFRoZSByZXBlYXRlZEludDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkQWxsUmVwZWF0ZWRJbnQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkSW50MzJJc011dGFibGUoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0TWVzc2FnZUxpdGUuQnVpbGRlci5hZGRBbGwoCiAgICAgICAgICAgIHZhbHVlcywgcmVwZWF0ZWRJbnQzMl8pOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgaW50MzIgcmVwZWF0ZWRfaW50MzIgPSAyMDQ4OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEludDMyKCkgewogICAgICAgIHJlcGVhdGVkSW50MzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0Lk5vblBhY2tlZEludDMyKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5Ob25QYWNrZWRJbnQzMikKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEludDMyKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRJbnQzMiBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPE5vblBhY2tlZEludDMyPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPE5vblBhY2tlZEludDMyPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgTm9uUGFja2VkSW50MzIgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOb25QYWNrZWRJbnQzMj4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOb25QYWNrZWRJbnQzMj4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkSW50MzIgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBQYWNrZWRGaXhlZDMyT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlBhY2tlZEZpeGVkMzIpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPiBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRml4ZWQzMi4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkRml4ZWQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLgogICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGaXhlZDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkRml4ZWQzMihpbnQgaW5kZXgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5QYWNrZWRGaXhlZDMyfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgUGFja2VkRml4ZWQzMiBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5QYWNrZWRGaXhlZDMyKQogICAgICBQYWNrZWRGaXhlZDMyT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBQYWNrZWRGaXhlZDMyLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFBhY2tlZEZpeGVkMzIoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBQYWNrZWRGaXhlZDMyKCkgewogICAgICByZXBlYXRlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgUGFja2VkRml4ZWQzMigpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9QYWNrZWRGaXhlZDMyX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1BhY2tlZEZpeGVkMzJfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0ZJWEVEMzJfRklFTERfTlVNQkVSID0gMjA0ODsKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkludExpc3QgcmVwZWF0ZWRGaXhlZDMyXyA9CiAgICAgICAgZW1wdHlJbnRMaXN0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAqIEByZXR1cm4gQSBsaXN0IGNvbnRhaW5pbmcgdGhlIHJlcGVhdGVkRml4ZWQzMi4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRml4ZWQzMihpbnQgaW5kZXgpIHsKICAgICAgcmV0dXJuIHJlcGVhdGVkRml4ZWQzMl8uZ2V0SW50KGluZGV4KTsKICAgIH0KICAgIHByaXZhdGUgaW50IHJlcGVhdGVkRml4ZWQzMk1lbW9pemVkU2VyaWFsaXplZFNpemUgPSAtMTsKCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIG91dHB1dC53cml0ZVVJbnQzMk5vVGFnKDE2Mzg2KTsKICAgICAgICBvdXRwdXQud3JpdGVVSW50MzJOb1RhZyhyZXBlYXRlZEZpeGVkMzJNZW1vaXplZFNlcmlhbGl6ZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlcGVhdGVkRml4ZWQzMl8uc2l6ZSgpOyBpKyspIHsKICAgICAgICBvdXRwdXQud3JpdGVGaXhlZDMyTm9UYWcocmVwZWF0ZWRGaXhlZDMyXy5nZXRJbnQoaSkpOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICB7CiAgICAgICAgaW50IGRhdGFTaXplID0gMDsKICAgICAgICBkYXRhU2l6ZSA9IDQgKiBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICAgIHNpemUgKz0gZGF0YVNpemU7CiAgICAgICAgaWYgKCFnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuaXNFbXB0eSgpKSB7CiAgICAgICAgICBzaXplICs9IDM7CiAgICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgICAuY29tcHV0ZUludDMyU2l6ZU5vVGFnKGRhdGFTaXplKTsKICAgICAgICB9CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyTWVtb2l6ZWRTZXJpYWxpemVkU2l6ZSA9IGRhdGFTaXplOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMikgb2JqOwoKICAgICAgaWYgKCFnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuUGFja2VkRml4ZWQzMn0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlBhY2tlZEZpeGVkMzIpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMk9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMi5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRGaXhlZDMyXyA9IHJlcGVhdGVkRml4ZWQzMl87CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMikgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMilvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlBhY2tlZEZpeGVkMzIuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRGaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEZpeGVkMzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfID0gb3RoZXIucmVwZWF0ZWRGaXhlZDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZEZpeGVkMzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDE2Mzg5OiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRGaXhlZDMyKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2Mzg5CiAgICAgICAgICAgICAgY2FzZSAxNjM4NjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZShhbGxvYyAvIDQpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEludChpbnB1dC5yZWFkRml4ZWQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjM4NgogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEZpeGVkMzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkRml4ZWQzMl8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkRml4ZWQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRGaXhlZDMyXywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRGaXhlZDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpIHsKICAgICAgICByZXBlYXRlZEZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkMzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgaW50IGdldFJlcGVhdGVkRml4ZWQzMkNvdW50KCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0OCBbcGFja2VkID0gdHJ1ZV07PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGaXhlZDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLmdldEludChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBzZXQgdGhlIHZhbHVlIGF0LgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkRml4ZWQzMiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRml4ZWQzMigKICAgICAgICAgIGludCBpbmRleCwgaW50IHZhbHVlKSB7CgogICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIHJlcGVhdGVkRml4ZWQzMl8uc2V0SW50KGluZGV4LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRGaXhlZDMyIHRvIGFkZC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaXhlZDMyKGludCB2YWx1ZSkgewoKICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEludCh2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4IFtwYWNrZWQgPSB0cnVlXTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkRml4ZWQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkRml4ZWQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZEZpeGVkMzJfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDggW3BhY2tlZCA9IHRydWVdOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZXBlYXRlZEZpeGVkMzIoKSB7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5QYWNrZWRGaXhlZDMyKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5QYWNrZWRGaXhlZDMyKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5QYWNrZWRGaXhlZDMyIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UGFja2VkRml4ZWQzMj4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxQYWNrZWRGaXhlZDMyPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgUGFja2VkRml4ZWQzMiBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFBhY2tlZEZpeGVkMzI+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8UGFja2VkRml4ZWQzMj4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUGFja2VkRml4ZWQzMiBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIE5vblBhY2tlZEZpeGVkMzJPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuTm9uUGFja2VkRml4ZWQzMikKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICogQHJldHVybiBBIGxpc3QgY29udGFpbmluZyB0aGUgcmVwZWF0ZWRGaXhlZDMyLgogICAgICovCiAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4OzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGNvdW50IG9mIHJlcGVhdGVkRml4ZWQzMi4KICAgICAqLwogICAgaW50IGdldFJlcGVhdGVkRml4ZWQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uCiAgICAgKiBAcmV0dXJuIFRoZSByZXBlYXRlZEZpeGVkMzIgYXQgdGhlIGdpdmVuIGluZGV4LgogICAgICovCiAgICBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyKGludCBpbmRleCk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0Lk5vblBhY2tlZEZpeGVkMzJ9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBOb25QYWNrZWRGaXhlZDMyIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0Lk5vblBhY2tlZEZpeGVkMzIpCiAgICAgIE5vblBhY2tlZEZpeGVkMzJPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIE5vblBhY2tlZEZpeGVkMzIubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgTm9uUGFja2VkRml4ZWQzMihjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIE5vblBhY2tlZEZpeGVkMzIoKSB7CiAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBlbXB0eUludExpc3QoKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBOb25QYWNrZWRGaXhlZDMyKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEZpeGVkMzJfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRklYRUQzMl9GSUVMRF9OVU1CRVIgPSAyMDQ4OwogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEZpeGVkMzJfID0KICAgICAgICBlbXB0eUludExpc3QoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjb3VudCBvZiByZXBlYXRlZEZpeGVkMzIuCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAqIEByZXR1cm4gVGhlIHJlcGVhdGVkRml4ZWQzMiBhdCB0aGUgZ2l2ZW4gaW5kZXguCiAgICAgKi8KICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyKGludCBpbmRleCkgewogICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXy5nZXRJbnQoaW5kZXgpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZXBlYXRlZEZpeGVkMzJfLnNpemUoKTsgaSsrKSB7CiAgICAgICAgb3V0cHV0LndyaXRlRml4ZWQzMigyMDQ4LCByZXBlYXRlZEZpeGVkMzJfLmdldEludChpKSk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHsKICAgICAgICBpbnQgZGF0YVNpemUgPSAwOwogICAgICAgIGRhdGFTaXplID0gNCAqIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKS5zaXplKCk7CiAgICAgICAgc2l6ZSArPSBkYXRhU2l6ZTsKICAgICAgICBzaXplICs9IDMgKiBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkuc2l6ZSgpOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMikgb2JqOwoKICAgICAgaWYgKCFnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkKICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVwZWF0ZWRGaXhlZDMyTGlzdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpID4gMCkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFJFUEVBVEVEX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldFJlcGVhdGVkRml4ZWQzMkxpc3QoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuTm9uUGFja2VkRml4ZWQzMn0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0Lk5vblBhY2tlZEZpeGVkMzIpCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMk9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMi5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXyA9IGVtcHR5SW50TGlzdCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgYnVpbGQoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgcmVzdWx0ID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMiByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICByZXN1bHQucmVwZWF0ZWRGaXhlZDMyXyA9IHJlcGVhdGVkRml4ZWQzMl87CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMikgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuTm9uUGFja2VkRml4ZWQzMilvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmICghb3RoZXIucmVwZWF0ZWRGaXhlZDMyXy5pc0VtcHR5KCkpIHsKICAgICAgICAgIGlmIChyZXBlYXRlZEZpeGVkMzJfLmlzRW1wdHkoKSkgewogICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfID0gb3RoZXIucmVwZWF0ZWRGaXhlZDMyXzsKICAgICAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEFsbChvdGhlci5yZXBlYXRlZEZpeGVkMzJfKTsKICAgICAgICAgIH0KICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDE2Mzg5OiB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IGlucHV0LnJlYWRGaXhlZDMyKCk7CiAgICAgICAgICAgICAgICBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKTsKICAgICAgICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8uYWRkSW50KHYpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE2Mzg5CiAgICAgICAgICAgICAgY2FzZSAxNjM4NjogewogICAgICAgICAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0LnJlYWRSYXdWYXJpbnQzMigpOwogICAgICAgICAgICAgICAgaW50IGxpbWl0ID0gaW5wdXQucHVzaExpbWl0KGxlbmd0aCk7CiAgICAgICAgICAgICAgICBpbnQgYWxsb2MgPSBsZW5ndGggPiA0MDk2ID8gNDA5NiA6IGxlbmd0aDsKICAgICAgICAgICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZShhbGxvYyAvIDQpOwogICAgICAgICAgICAgICAgd2hpbGUgKGlucHV0LmdldEJ5dGVzVW50aWxMaW1pdCgpID4gMCkgewogICAgICAgICAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfLmFkZEludChpbnB1dC5yZWFkRml4ZWQzMigpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlucHV0LnBvcExpbWl0KGxpbWl0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNjM4NgogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuSW50TGlzdCByZXBlYXRlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgIHByaXZhdGUgdm9pZCBlbnN1cmVSZXBlYXRlZEZpeGVkMzJJc011dGFibGUoKSB7CiAgICAgICAgaWYgKCFyZXBlYXRlZEZpeGVkMzJfLmlzTW9kaWZpYWJsZSgpKSB7CiAgICAgICAgICByZXBlYXRlZEZpeGVkMzJfID0gbWFrZU11dGFibGVDb3B5KHJlcGVhdGVkRml4ZWQzMl8pOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgIH0KICAgICAgcHJpdmF0ZSB2b2lkIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZShpbnQgY2FwYWNpdHkpIHsKICAgICAgICBpZiAoIXJlcGVhdGVkRml4ZWQzMl8uaXNNb2RpZmlhYmxlKCkpIHsKICAgICAgICAgIHJlcGVhdGVkRml4ZWQzMl8gPSBtYWtlTXV0YWJsZUNvcHkocmVwZWF0ZWRGaXhlZDMyXywgY2FwYWNpdHkpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIEEgbGlzdCBjb250YWluaW5nIHRoZSByZXBlYXRlZEZpeGVkMzIuCiAgICAgICAqLwogICAgICBwdWJsaWMgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRSZXBlYXRlZEZpeGVkMzJMaXN0KCkgewogICAgICAgIHJlcGVhdGVkRml4ZWQzMl8ubWFrZUltbXV0YWJsZSgpOwogICAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXBlYXRlZCBmaXhlZDMyIHJlcGVhdGVkX2ZpeGVkMzIgPSAyMDQ4OzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgY291bnQgb2YgcmVwZWF0ZWRGaXhlZDMyLgogICAgICAgKi8KICAgICAgcHVibGljIGludCBnZXRSZXBlYXRlZEZpeGVkMzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gcmVwZWF0ZWRGaXhlZDMyXy5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi4KICAgICAgICogQHJldHVybiBUaGUgcmVwZWF0ZWRGaXhlZDMyIGF0IHRoZSBnaXZlbiBpbmRleC4KICAgICAgICovCiAgICAgIHB1YmxpYyBpbnQgZ2V0UmVwZWF0ZWRGaXhlZDMyKGludCBpbmRleCkgewogICAgICAgIHJldHVybiByZXBlYXRlZEZpeGVkMzJfLmdldEludChpbmRleCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHNldCB0aGUgdmFsdWUgYXQuCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgcmVwZWF0ZWRGaXhlZDMyIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaXhlZDMyKAogICAgICAgICAgaW50IGluZGV4LCBpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5zZXRJbnQoaW5kZXgsIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHJlcGVhdGVkRml4ZWQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRml4ZWQzMihpbnQgdmFsdWUpIHsKCiAgICAgICAgZW5zdXJlUmVwZWF0ZWRGaXhlZDMySXNNdXRhYmxlKCk7CiAgICAgICAgcmVwZWF0ZWRGaXhlZDMyXy5hZGRJbnQodmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVwZWF0ZWQgZml4ZWQzMiByZXBlYXRlZF9maXhlZDMyID0gMjA0ODs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZXMgVGhlIHJlcGVhdGVkRml4ZWQzMiB0byBhZGQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZEFsbFJlcGVhdGVkRml4ZWQzMigKICAgICAgICAgIGphdmEubGFuZy5JdGVyYWJsZTw/IGV4dGVuZHMgamF2YS5sYW5nLkludGVnZXI+IHZhbHVlcykgewogICAgICAgIGVuc3VyZVJlcGVhdGVkRml4ZWQzMklzTXV0YWJsZSgpOwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RNZXNzYWdlTGl0ZS5CdWlsZGVyLmFkZEFsbCgKICAgICAgICAgICAgdmFsdWVzLCByZXBlYXRlZEZpeGVkMzJfKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcGVhdGVkIGZpeGVkMzIgcmVwZWF0ZWRfZml4ZWQzMiA9IDIwNDg7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclJlcGVhdGVkRml4ZWQzMigpIHsKICAgICAgICByZXBlYXRlZEZpeGVkMzJfID0gZW1wdHlJbnRMaXN0KCk7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0Lk5vblBhY2tlZEZpeGVkMzIpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0Lk5vblBhY2tlZEZpeGVkMzIpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk5vblBhY2tlZEZpeGVkMzIgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOb25QYWNrZWRGaXhlZDMyPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPE5vblBhY2tlZEZpeGVkMzI+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBOb25QYWNrZWRGaXhlZDMyIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8Tm9uUGFja2VkRml4ZWQzMj4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxOb25QYWNrZWRGaXhlZDMyPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Ob25QYWNrZWRGaXhlZDMyIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgRHVwRW51bU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5EdXBFbnVtKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewogIH0KICAvKioKICAgKiA8cHJlPgogICAqIFRlc3QgYW4gZW51bSB0aGF0IGhhcyBtdWx0aXBsZSB2YWx1ZXMgd2l0aCB0aGUgc2FtZSBudW1iZXIuCiAgICogPC9wcmU+CiAgICoKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5EdXBFbnVtfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgRHVwRW51bSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5EdXBFbnVtKQogICAgICBEdXBFbnVtT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBEdXBFbnVtLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIER1cEVudW0oY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBEdXBFbnVtKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IER1cEVudW0oKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRHVwRW51bV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9EdXBFbnVtX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5jbGFzcywgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICAvKioKICAgICAqIFByb3RvYnVmIGVudW0ge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LkR1cEVudW0uVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlfQogICAgICovCiAgICBwdWJsaWMgZW51bSBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGUKICAgICAgICBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xNZXNzYWdlRW51bSB7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5GT08xID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBGT08xKDEpLAogICAgICAvKioKICAgICAgICogPGNvZGU+QkFSMSA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQkFSMSgyKSwKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkJBWiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgQkFaKDMpLAogICAgICA7CgogICAgICAvKioKICAgICAgICogPGNvZGU+Rk9PMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGUgRk9PMiA9IEZPTzE7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5CQVIyID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZSBCQVIyID0gQkFSMTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkZPTzEgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEZPTzFfVkFMVUUgPSAxOwogICAgICAvKioKICAgICAgICogPGNvZGU+QkFSMSA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgQkFSMV9WQUxVRSA9IDI7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5CQVogPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEJBWl9WQUxVRSA9IDM7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5GT08yID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBGT08yX1ZBTFVFID0gMTsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPkJBUjIgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEJBUjJfVkFMVUUgPSAyOwoKCiAgICAgIHB1YmxpYyBmaW5hbCBpbnQgZ2V0TnVtYmVyKCkgewogICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgI2Zvck51bWJlcihpbnQpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBzdGF0aWMgVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICAgIH0KCiAgICAgIC8qKgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICAgKi8KICAgICAgcHVibGljIHN0YXRpYyBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGUgZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICAgIGNhc2UgMTogcmV0dXJuIEZPTzE7CiAgICAgICAgICBjYXNlIDI6IHJldHVybiBCQVIxOwogICAgICAgICAgY2FzZSAzOiByZXR1cm4gQkFaOwogICAgICAgICAgZGVmYXVsdDogcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8VGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlPgogICAgICAgICAgaW50ZXJuYWxHZXRWYWx1ZU1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxWYWx1ZU1hcDsKICAgICAgfQogICAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPAogICAgICAgICAgVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlPiBpbnRlcm5hbFZhbHVlTWFwID0KICAgICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8VGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlPigpIHsKICAgICAgICAgICAgICBwdWJsaWMgVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlIGZpbmRWYWx1ZUJ5TnVtYmVyKGludCBudW1iZXIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBUZXN0RW51bVdpdGhEdXBWYWx1ZUxpdGUuZm9yTnVtYmVyKG51bWJlcik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9OwoKICAgICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvcgogICAgICAgICAgZ2V0VmFsdWVEZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCkuZ2V0VmFsdWVzKCkuZ2V0KG9yZGluYWwoKSk7CiAgICAgIH0KICAgICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCk7CiAgICAgIH0KICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtLmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMCk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZVtdIFZBTFVFUyA9IGdldFN0YXRpY1ZhbHVlc0FycmF5KCk7CiAgICAgIHByaXZhdGUgc3RhdGljIFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZVtdIGdldFN0YXRpY1ZhbHVlc0FycmF5KCkgewogICAgICAgIHJldHVybiBuZXcgVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlW10gewogICAgICAgIEZPTzEsIEJBUjEsIEJBWiwgRk9PMiwgQkFSMiwgCiAgICAgICAgfTsKICAgICAgfQogICAgICBwdWJsaWMgc3RhdGljIFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZSB2YWx1ZU9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yIGRlc2MpIHsKICAgICAgICBpZiAoZGVzYy5nZXRUeXBlKCkgIT0gZ2V0RGVzY3JpcHRvcigpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigKICAgICAgICAgICAgIkVudW1WYWx1ZURlc2NyaXB0b3IgaXMgbm90IGZvciB0aGlzIHR5cGUuIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBWQUxVRVNbZGVzYy5nZXRJbmRleCgpXTsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CgogICAgICBwcml2YXRlIFRlc3RFbnVtV2l0aER1cFZhbHVlTGl0ZShpbnQgdmFsdWUpIHsKICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICAgIH0KCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChlbnVtX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LkR1cEVudW0uVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlKQogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0pKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSkgb2JqOwoKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIDxwcmU+CiAgICAgKiBUZXN0IGFuIGVudW0gdGhhdCBoYXMgbXVsdGlwbGUgdmFsdWVzIHdpdGggdGhlIHNhbWUgbnVtYmVyLgogICAgICogPC9wcmU+CiAgICAgKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuRHVwRW51bX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LkR1cEVudW0pCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRHVwRW51bV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRHVwRW51bV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtLmNsYXNzLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9EdXBFbnVtX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0gZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBidWlsZCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSByZXN1bHQgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSh0aGlzKTsKICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0pIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkR1cEVudW0pb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5EdXBFbnVtKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5EdXBFbnVtKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5EdXBFbnVtIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8RHVwRW51bT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxEdXBFbnVtPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgRHVwRW51bSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPER1cEVudW0+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8RHVwRW51bT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRHVwRW51bSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFJlY3Vyc2l2ZU1lc3NhZ2VPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlIHJlY3Vyc2UgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgcmVjdXJzZSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzUmVjdXJzZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSByZWN1cnNlLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIGdldFJlY3Vyc2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlT3JCdWlsZGVyIGdldFJlY3Vyc2VPckJ1aWxkZXIoKTsKCiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIHBheWxvYWQgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgcGF5bG9hZCBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzUGF5bG9hZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBwYXlsb2FkID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBwYXlsb2FkLgogICAgICovCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0UGF5bG9hZCgpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgUmVjdXJzaXZlTWVzc2FnZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlKQogICAgICBSZWN1cnNpdmVNZXNzYWdlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBSZWN1cnNpdmVNZXNzYWdlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFJlY3Vyc2l2ZU1lc3NhZ2UoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBSZWN1cnNpdmVNZXNzYWdlKCkgewogICAgICBwYXlsb2FkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBSZWN1cnNpdmVNZXNzYWdlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlY3Vyc2l2ZU1lc3NhZ2VfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUmVjdXJzaXZlTWVzc2FnZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFQ1VSU0VfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlXzsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSByZWN1cnNlIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzUmVjdXJzZSgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSByZWN1cnNlLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBnZXRSZWN1cnNlKCkgewogICAgICByZXR1cm4gcmVjdXJzZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiByZWN1cnNlXzsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZU9yQnVpbGRlciBnZXRSZWN1cnNlT3JCdWlsZGVyKCkgewogICAgICByZXR1cm4gcmVjdXJzZV8gPT0gbnVsbCA/IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkgOiByZWN1cnNlXzsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQVlMT0FEX0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBwYXlsb2FkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgYnl0ZXMgcGF5bG9hZCA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBwYXlsb2FkIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzUGF5bG9hZCgpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBwYXlsb2FkID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBwYXlsb2FkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldFBheWxvYWQoKSB7CiAgICAgIHJldHVybiBwYXlsb2FkXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZU1lc3NhZ2UoMSwgZ2V0UmVjdXJzZSgpKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVCeXRlcygyLCBwYXlsb2FkXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxLCBnZXRSZWN1cnNlKCkpOwogICAgICB9CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVCeXRlc1NpemUoMiwgcGF5bG9hZF8pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2Ugb3RoZXIgPSAoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSkgb2JqOwoKICAgICAgaWYgKGhhc1JlY3Vyc2UoKSAhPSBvdGhlci5oYXNSZWN1cnNlKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc1JlY3Vyc2UoKSkgewogICAgICAgIGlmICghZ2V0UmVjdXJzZSgpCiAgICAgICAgICAgIC5lcXVhbHMob3RoZXIuZ2V0UmVjdXJzZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNQYXlsb2FkKCkgIT0gb3RoZXIuaGFzUGF5bG9hZCgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNQYXlsb2FkKCkpIHsKICAgICAgICBpZiAoIWdldFBheWxvYWQoKQogICAgICAgICAgICAuZXF1YWxzKG90aGVyLmdldFBheWxvYWQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmIChoYXNSZWN1cnNlKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBSRUNVUlNFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRSZWN1cnNlKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoaGFzUGF5bG9hZCgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgUEFZTE9BRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0UGF5bG9hZCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSkKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuY2xhc3MsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CiAgICAgICAgbWF5YmVGb3JjZUJ1aWxkZXJJbml0aWFsaXphdGlvbigpOwogICAgICB9CiAgICAgIHByaXZhdGUgdm9pZCBtYXliZUZvcmNlQnVpbGRlckluaXRpYWxpemF0aW9uKCkgewogICAgICAgIGlmIChjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgICAgICAgLmFsd2F5c1VzZUZpZWxkQnVpbGRlcnMpIHsKICAgICAgICAgIGdldFJlY3Vyc2VGaWVsZEJ1aWxkZXIoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIHJlY3Vyc2VfID0gbnVsbDsKICAgICAgICBpZiAocmVjdXJzZUJ1aWxkZXJfICE9IG51bGwpIHsKICAgICAgICAgIHJlY3Vyc2VCdWlsZGVyXy5kaXNwb3NlKCk7CiAgICAgICAgICByZWN1cnNlQnVpbGRlcl8gPSBudWxsOwogICAgICAgIH0KICAgICAgICBwYXlsb2FkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5FTVBUWTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlY3Vyc2l2ZU1lc3NhZ2VfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIGJ1aWxkKCkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlIHJlc3VsdCA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQucmVjdXJzZV8gPSByZWN1cnNlQnVpbGRlcl8gPT0gbnVsbAogICAgICAgICAgICAgID8gcmVjdXJzZV8KICAgICAgICAgICAgICA6IHJlY3Vyc2VCdWlsZGVyXy5idWlsZCgpOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIH0KICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LnBheWxvYWRfID0gcGF5bG9hZF87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5iaXRGaWVsZDBfIHw9IHRvX2JpdEZpZWxkMF87CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaWYgKG90aGVyLmhhc1JlY3Vyc2UoKSkgewogICAgICAgICAgbWVyZ2VSZWN1cnNlKG90aGVyLmdldFJlY3Vyc2UoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNQYXlsb2FkKCkpIHsKICAgICAgICAgIHNldFBheWxvYWQob3RoZXIuZ2V0UGF5bG9hZCgpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAxMDogewogICAgICAgICAgICAgICAgaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgZ2V0UmVjdXJzZUZpZWxkQnVpbGRlcigpLmdldEJ1aWxkZXIoKSwKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTAKICAgICAgICAgICAgICBjYXNlIDE4OiB7CiAgICAgICAgICAgICAgICBwYXlsb2FkXyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDE4CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5CdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlT3JCdWlsZGVyPiByZWN1cnNlQnVpbGRlcl87CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgcmVjdXJzZSBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNSZWN1cnNlKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSByZWN1cnNlLgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgZ2V0UmVjdXJzZSgpIHsKICAgICAgICBpZiAocmVjdXJzZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZWN1cnNlXyA9PSBudWxsID8gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSA6IHJlY3Vyc2VfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVjdXJzZUJ1aWxkZXJfLmdldE1lc3NhZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlIHJlY3Vyc2UgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlY3Vyc2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChyZWN1cnNlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgICByZWN1cnNlXyA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZWN1cnNlQnVpbGRlcl8uc2V0TWVzc2FnZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVjdXJzZSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuQnVpbGRlciBidWlsZGVyRm9yVmFsdWUpIHsKICAgICAgICBpZiAocmVjdXJzZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlY3Vyc2VfID0gYnVpbGRlckZvclZhbHVlLmJ1aWxkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlY3Vyc2VCdWlsZGVyXy5zZXRNZXNzYWdlKGJ1aWxkZXJGb3JWYWx1ZS5idWlsZCgpKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZVJlY3Vyc2UoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSB2YWx1ZSkgewogICAgICAgIGlmIChyZWN1cnNlQnVpbGRlcl8gPT0gbnVsbCkgewogICAgICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApICYmCiAgICAgICAgICAgIHJlY3Vyc2VfICE9IG51bGwgJiYKICAgICAgICAgICAgcmVjdXJzZV8gIT0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgewogICAgICAgICAgICBnZXRSZWN1cnNlQnVpbGRlcigpLm1lcmdlRnJvbSh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZWN1cnNlXyA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZWN1cnNlQnVpbGRlcl8ubWVyZ2VGcm9tKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJlY3Vyc2VfICE9IG51bGwpIHsKICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgLnByb3RvYnVmX3VuaXR0ZXN0LlJlY3Vyc2l2ZU1lc3NhZ2UgcmVjdXJzZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJSZWN1cnNlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICByZWN1cnNlXyA9IG51bGw7CiAgICAgICAgaWYgKHJlY3Vyc2VCdWlsZGVyXyAhPSBudWxsKSB7CiAgICAgICAgICByZWN1cnNlQnVpbGRlcl8uZGlzcG9zZSgpOwogICAgICAgICAgcmVjdXJzZUJ1aWxkZXJfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIC5wcm90b2J1Zl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlIHJlY3Vyc2UgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLkJ1aWxkZXIgZ2V0UmVjdXJzZUJ1aWxkZXIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBnZXRSZWN1cnNlRmllbGRCdWlsZGVyKCkuZ2V0QnVpbGRlcigpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZU9yQnVpbGRlciBnZXRSZWN1cnNlT3JCdWlsZGVyKCkgewogICAgICAgIGlmIChyZWN1cnNlQnVpbGRlcl8gIT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJlY3Vyc2VCdWlsZGVyXy5nZXRNZXNzYWdlT3JCdWlsZGVyKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiByZWN1cnNlXyA9PSBudWxsID8KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpIDogcmVjdXJzZV87CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCAucHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSByZWN1cnNlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuU2luZ2xlRmllbGRCdWlsZGVyVjM8CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZWN1cnNpdmVNZXNzYWdlLkJ1aWxkZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2VPckJ1aWxkZXI+IAogICAgICAgICAgZ2V0UmVjdXJzZUZpZWxkQnVpbGRlcigpIHsKICAgICAgICBpZiAocmVjdXJzZUJ1aWxkZXJfID09IG51bGwpIHsKICAgICAgICAgIHJlY3Vyc2VCdWlsZGVyXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLlNpbmdsZUZpZWxkQnVpbGRlclYzPAogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UuQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZU9yQnVpbGRlcj4oCiAgICAgICAgICAgICAgICAgIGdldFJlY3Vyc2UoKSwKICAgICAgICAgICAgICAgICAgZ2V0UGFyZW50Rm9yQ2hpbGRyZW4oKSwKICAgICAgICAgICAgICAgICAgaXNDbGVhbigpKTsKICAgICAgICAgIHJlY3Vyc2VfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlY3Vyc2VCdWlsZGVyXzsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgcGF5bG9hZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFk7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBwYXlsb2FkID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgcGF5bG9hZCBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc1BheWxvYWQoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBwYXlsb2FkID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIHBheWxvYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0UGF5bG9hZCgpIHsKICAgICAgICByZXR1cm4gcGF5bG9hZF87CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm9wdGlvbmFsIGJ5dGVzIHBheWxvYWQgPSAyOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBwYXlsb2FkIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UGF5bG9hZChjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgdmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsgfQogICAgICAgIHBheWxvYWRfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBieXRlcyBwYXlsb2FkID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyUGF5bG9hZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgcGF5bG9hZF8gPSBnZXREZWZhdWx0SW5zdGFuY2UoKS5nZXRQYXlsb2FkKCk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuUmVjdXJzaXZlTWVzc2FnZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVjdXJzaXZlTWVzc2FnZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlY3Vyc2l2ZU1lc3NhZ2U+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8UmVjdXJzaXZlTWVzc2FnZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFJlY3Vyc2l2ZU1lc3NhZ2UgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxSZWN1cnNpdmVNZXNzYWdlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFJlY3Vyc2l2ZU1lc3NhZ2U+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlY3Vyc2l2ZU1lc3NhZ2UgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfSU5UMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTsKICAvKioKICAgKiA8cHJlPgogICAqIFNpbmd1bGFyCiAgICogPC9wcmU+CiAgICoKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkludGVnZXI+IG9wdGlvbmFsSW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9JTlQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gb3B0aW9uYWxJbnQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1VJTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gb3B0aW9uYWxVaW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9VSU5UNjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkxvbmc+IG9wdGlvbmFsVWludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfU0lOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDU7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5JbnRlZ2VyPiBvcHRpb25hbFNpbnQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NJTlQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA2OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gb3B0aW9uYWxTaW50NjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9GSVhFRDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDc7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5JbnRlZ2VyPiBvcHRpb25hbEZpeGVkMzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9GSVhFRDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDg7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5Mb25nPiBvcHRpb25hbEZpeGVkNjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9TRklYRUQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gb3B0aW9uYWxTZml4ZWQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NGSVhFRDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDEwOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gb3B0aW9uYWxTZml4ZWQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0ZMT0FUX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDExOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuRmxvYXQ+IG9wdGlvbmFsRmxvYXRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuRmxvYXQuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfRE9VQkxFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDEyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuRG91YmxlPiBvcHRpb25hbERvdWJsZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Eb3VibGUuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfQk9PTF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkJvb2xlYW4+IG9wdGlvbmFsQm9vbEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Cb29sZWFuLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX1NUUklOR19FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxNDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLlN0cmluZz4gb3B0aW9uYWxTdHJpbmdFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0JZVEVTX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDE1OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG9wdGlvbmFsQnl0ZXNFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxHUk9VUF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxNjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZT4gb3B0aW9uYWxHcm91cEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLk9wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGUuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfTkVTVEVEX01FU1NBR0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTg7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZT4gb3B0aW9uYWxOZXN0ZWRNZXNzYWdlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmNsYXNzLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfRk9SRUlHTl9NRVNTQUdFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDE5OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9JTVBPUlRfTUVTU0FHRV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAyMDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGU+IG9wdGlvbmFsSW1wb3J0TWVzc2FnZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmNsYXNzLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9ORVNURURfRU5VTV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAyMTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtPiBvcHRpb25hbE5lc3RlZEVudW1FeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfRk9SRUlHTl9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDIyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IG9wdGlvbmFsRm9yZWlnbkVudW1FeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGUuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfSU1QT1JUX0VOVU1fRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjM7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlPiBvcHRpb25hbEltcG9ydEVudW1FeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9TVFJJTkdfUElFQ0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjQ7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5TdHJpbmc+IG9wdGlvbmFsU3RyaW5nUGllY2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9QVElPTkFMX0NPUkRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjU7CiAgLyoqCiAgICogPHByZT4KICAgKiBUT0RPOiBjdHlwZT1DT1JEIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGV4dGVuc2lvbi4gQWRkCiAgICogY3R5cGU9Q09SRCBvcHRpb24gYmFjayBhZnRlciBpdCBpcyBzdXBwb3J0ZWQuCiAgICogPC9wcmU+CiAgICoKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLlN0cmluZz4gb3B0aW9uYWxDb3JkRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLlN0cmluZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9QVUJMSUNfSU1QT1JUX01FU1NBR0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMjY7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRQdWJsaWNMaXRlLlB1YmxpY0ltcG9ydE1lc3NhZ2VMaXRlPiBvcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5QdWJsaWNJbXBvcnRNZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT1BUSU9OQUxfTEFaWV9NRVNTQUdFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDI3OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+IG9wdGlvbmFsTGF6eU1lc3NhZ2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPUFRJT05BTF9VTlZFUklGSUVEX0xBWllfTUVTU0FHRV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAyODsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDMxOwogIC8qKgogICAqIDxwcmU+CiAgICogUmVwZWF0ZWQKICAgKiA8L3ByZT4KICAgKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4+IHJlcGVhdGVkSW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9JTlQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAzMjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+PiByZXBlYXRlZEludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfVUlOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDMzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4+IHJlcGVhdGVkVWludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfVUlOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDM0OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHJlcGVhdGVkVWludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfU0lOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDM1OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4+IHJlcGVhdGVkU2ludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfU0lOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDM2OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHJlcGVhdGVkU2ludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRklYRUQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAzNzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+PiByZXBlYXRlZEZpeGVkMzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9GSVhFRDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDM4OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHJlcGVhdGVkRml4ZWQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1NGSVhFRDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDM5OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4+IHJlcGVhdGVkU2ZpeGVkMzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9TRklYRUQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA0MDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+PiByZXBlYXRlZFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRkxPQVRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDE7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5GbG9hdD4+IHJlcGVhdGVkRmxvYXRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuRmxvYXQuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRE9VQkxFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDQyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRG91YmxlPj4gcmVwZWF0ZWREb3VibGVFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuRG91YmxlLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0JPT0xfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDM7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Cb29sZWFuPj4gcmVwZWF0ZWRCb29sRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkJvb2xlYW4uY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfU1RSSU5HX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDQ0OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuU3RyaW5nPj4gcmVwZWF0ZWRTdHJpbmdFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0JZVEVTX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDQ1OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+PiByZXBlYXRlZEJ5dGVzRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVER1JPVVBfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNDY7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGU+PiByZXBlYXRlZEdyb3VwRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBSRVBFQVRFRF9ORVNURURfTUVTU0FHRV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA0ODsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPj4gcmVwZWF0ZWROZXN0ZWRNZXNzYWdlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmNsYXNzLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRk9SRUlHTl9NRVNTQUdFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDQ5OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+PiByZXBlYXRlZEZvcmVpZ25NZXNzYWdlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLmNsYXNzLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfSU1QT1JUX01FU1NBR0VfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNTA7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydE1lc3NhZ2VMaXRlPj4gcmVwZWF0ZWRJbXBvcnRNZXNzYWdlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdEltcG9ydExpdGUuSW1wb3J0TWVzc2FnZUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX05FU1RFRF9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDUxOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+PiByZXBlYXRlZE5lc3RlZEVudW1FeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0uY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfRk9SRUlHTl9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDUyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+PiByZXBlYXRlZEZvcmVpZ25FbnVtRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0lNUE9SVF9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDUzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4+IHJlcGVhdGVkSW1wb3J0RW51bUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RJbXBvcnRMaXRlLkltcG9ydEVudW1MaXRlLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX1NUUklOR19QSUVDRV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA1NDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLlN0cmluZz4+IHJlcGVhdGVkU3RyaW5nUGllY2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFJFUEVBVEVEX0NPUkRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNTU7CiAgLyoqCiAgICogPHByZT4KICAgKiBUT0RPOiBjdHlwZT1DT1JEIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGV4dGVuc2lvbi4gQWRkCiAgICogY3R5cGU9Q09SRCBvcHRpb24gYmFjayBhZnRlciBpdCBpcyBzdXBwb3J0ZWQuCiAgICogPC9wcmU+CiAgICoKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLlN0cmluZz4+IHJlcGVhdGVkQ29yZEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUkVQRUFURURfTEFaWV9NRVNTQUdFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDU3OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2U+PiByZXBlYXRlZExhenlNZXNzYWdlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmNsYXNzLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9JTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA2MTsKICAvKioKICAgKiA8cHJlPgogICAqIFNpbmd1bGFyIHdpdGggZGVmYXVsdHMKICAgKiA8L3ByZT4KICAgKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9JTlQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA2MjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRJbnQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfVUlOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDYzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdFVpbnQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfVUlOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDY0OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdFVpbnQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU0lOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDY1OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdFNpbnQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU0lOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDY2OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdFNpbnQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfRklYRUQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA2NzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRGaXhlZDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9GSVhFRDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDY4OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdEZpeGVkNjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1NGSVhFRDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDY5OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdFNmaXhlZDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgREVGQVVMVF9TRklYRUQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA3MDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRTZml4ZWQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfRkxPQVRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNzE7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5GbG9hdD4gZGVmYXVsdEZsb2F0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkZsb2F0LmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfRE9VQkxFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDcyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuRG91YmxlPiBkZWZhdWx0RG91YmxlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkRvdWJsZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0JPT0xfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gNzM7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5Cb29sZWFuPiBkZWZhdWx0Qm9vbEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Cb29sZWFuLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfU1RSSU5HX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDc0OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuU3RyaW5nPiBkZWZhdWx0U3RyaW5nRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLlN0cmluZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0JZVEVTX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDc1OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IGRlZmF1bHRCeXRlc0V4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX05FU1RFRF9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDgxOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW0+IGRlZmF1bHROZXN0ZWRFbnVtRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IERFRkFVTFRfRk9SRUlHTl9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDgyOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduRW51bUxpdGU+IGRlZmF1bHRGb3JlaWduRW51bUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0lNUE9SVF9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDgzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZT4gZGVmYXVsdEltcG9ydEVudW1FeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5JbXBvcnRFbnVtTGl0ZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX1NUUklOR19QSUVDRV9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA4NDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLlN0cmluZz4gZGVmYXVsdFN0cmluZ1BpZWNlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLlN0cmluZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBERUZBVUxUX0NPUkRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gODU7CiAgLyoqCiAgICogPHByZT4KICAgKiBUT0RPOiBjdHlwZT1DT1JEIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGV4dGVuc2lvbi4gQWRkCiAgICogY3R5cGU9Q09SRCBvcHRpb24gYmFjayBhZnRlciBpdCBpcyBzdXBwb3J0ZWQuCiAgICogPC9wcmU+CiAgICoKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS5sYW5nLlN0cmluZz4gZGVmYXVsdENvcmRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX1VJTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMTE7CiAgLyoqCiAgICogPHByZT4KICAgKiBGb3Igb25lb2YgdGVzdAogICAqIDwvcHJlPgogICAqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEubGFuZy5JbnRlZ2VyPiBvbmVvZlVpbnQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE9ORU9GX05FU1RFRF9NRVNTQUdFX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDExMjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxFeHRlbnNpb25zTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlPiBvbmVvZk5lc3RlZE1lc3NhZ2VFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2UuY2xhc3MsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBPTkVPRl9TVFJJTkdfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTEzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLmxhbmcuU3RyaW5nPiBvbmVvZlN0cmluZ0V4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgT05FT0ZfQllURVNfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTE0OwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG9uZW9mQnl0ZXNFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0lOVDMyX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDkwOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuSW50ZWdlcj4+IHBhY2tlZEludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0lOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDkxOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHBhY2tlZEludDY0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkxvbmcuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1VJTlQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5MjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+PiBwYWNrZWRVaW50MzJFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlci5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfVUlOVDY0X0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDkzOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuTG9uZz4+IHBhY2tlZFVpbnQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9TSU5UMzJfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gOTQ7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5JbnRlZ2VyPj4gcGFja2VkU2ludDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX1NJTlQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5NTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+PiBwYWNrZWRTaW50NjRFeHRlbnNpb25MaXRlID0gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlCiAgICAgICAgICAubmV3RmlsZVNjb3BlZEdlbmVyYXRlZEV4dGVuc2lvbigKICAgICAgICBqYXZhLmxhbmcuTG9uZy5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfRklYRUQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5NjsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+PiBwYWNrZWRGaXhlZDMyRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkludGVnZXIuY2xhc3MsCiAgICAgICAgbnVsbCk7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUEFDS0VEX0ZJWEVENjRfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gOTc7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Mb25nPj4gcGFja2VkRml4ZWQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9TRklYRUQzMl9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5ODsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkludGVnZXI+PiBwYWNrZWRTZml4ZWQzMkV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9TRklYRUQ2NF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSA5OTsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8amF2YS5sYW5nLkxvbmc+PiBwYWNrZWRTZml4ZWQ2NEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Mb25nLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9GTE9BVF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMDA7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5GbG9hdD4+IHBhY2tlZEZsb2F0RXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkZsb2F0LmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9ET1VCTEVfRVhURU5TSU9OX0xJVEVfRklFTERfTlVNQkVSID0gMTAxOwogIC8qKgogICAqIDxjb2RlPmV4dGVuZCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlIHsgLi4uIH08L2NvZGU+CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlLkdlbmVyYXRlZEV4dGVuc2lvbjwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlLAogICAgICBqYXZhLnV0aWwuTGlzdDxqYXZhLmxhbmcuRG91YmxlPj4gcGFja2VkRG91YmxlRXh0ZW5zaW9uTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgamF2YS5sYW5nLkRvdWJsZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQQUNLRURfQk9PTF9FWFRFTlNJT05fTElURV9GSUVMRF9OVU1CRVIgPSAxMDI7CiAgLyoqCiAgICogPGNvZGU+ZXh0ZW5kIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUgeyAuLi4gfTwvY29kZT4KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UuR2VuZXJhdGVkRXh0ZW5zaW9uPAogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUsCiAgICAgIGphdmEudXRpbC5MaXN0PGphdmEubGFuZy5Cb29sZWFuPj4gcGFja2VkQm9vbEV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGphdmEubGFuZy5Cb29sZWFuLmNsYXNzLAogICAgICAgIG51bGwpOwogIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBBQ0tFRF9FTlVNX0VYVEVOU0lPTl9MSVRFX0ZJRUxEX05VTUJFUiA9IDEwMzsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSwKICAgICAgamF2YS51dGlsLkxpc3Q8Y29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbkVudW1MaXRlPj4gcGFja2VkRW51bUV4dGVuc2lvbkxpdGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgIC5uZXdGaWxlU2NvcGVkR2VuZXJhdGVkRXh0ZW5zaW9uKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25FbnVtTGl0ZS5jbGFzcywKICAgICAgICBudWxsKTsKICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBURVNUX0FMTF9UWVBFU19MSVRFX0ZJRUxEX05VTUJFUiA9IDUzNjg2MDAwMDsKICAvKioKICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RIdWdlRmllbGROdW1iZXJzTGl0ZSwKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gdGVzdEFsbFR5cGVzTGl0ZSA9IGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZQogICAgICAgICAgLm5ld0ZpbGVTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5jbGFzcywKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2VfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZTJfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlMl9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfUmVwZWF0ZWRHcm91cF9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhY2tlZFR5cGVzTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X09wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE5lc3RlZEV4dGVuc2lvbkxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3REZXByZWNhdGVkTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAxX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAyX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMl9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9PcHRpb25hbEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXJnZUV4Y2VwdGlvbkxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZUxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVjFNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMU1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9PcHRpb25hbEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfU3RyaW5nU3RyaW5nTWFwRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX1N0cmluZ1N0cmluZ01hcEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VTZXRMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlU2V0TGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUGFja2VkSW50MzJfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUGFja2VkSW50MzJfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9QYWNrZWRGaXhlZDMyX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1BhY2tlZEZpeGVkMzJfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEZpeGVkMzJfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfTm9uUGFja2VkRml4ZWQzMl9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRHVwRW51bV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9EdXBFbnVtX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlY3Vyc2l2ZU1lc3NhZ2VfZmllbGRBY2Nlc3NvclRhYmxlOwoKICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3IKICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgIHJldHVybiBkZXNjcmlwdG9yOwogIH0KICBwcml2YXRlIHN0YXRpYyAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICBkZXNjcmlwdG9yOwogIHN0YXRpYyB7CiAgICBqYXZhLmxhbmcuU3RyaW5nW10gZGVzY3JpcHRvckRhdGEgPSB7CiAgICAgICJcbiNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfbGl0ZS5wcm90b1wwMjJcMDIxcCIgKwogICAgICAicm90b2J1Zl91bml0dGVzdFwwMzIqZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZSIgKwogICAgICAic3RfaW1wb3J0X2xpdGUucHJvdG9cIlwyNTFcMDM0XG5cMDIwVGVzdEFsbFR5cGVzTGl0IiArCiAgICAgICJlXDAyMlwwMjZcblwwMTZvcHRpb25hbF9pbnQzMlwwMzBcMDAxIFwwMDEoXDAwNVwwMjJcMDI2XG5cMDE2b3B0aW9uYWxfaW4iICsKICAgICAgInQ2NFwwMzBcMDAyIFwwMDEoXDAwM1wwMjJcMDI3XG5cMDE3b3B0aW9uYWxfdWludDMyXDAzMFwwMDMgXDAwMShcclwwMjJcMDI3XG5cMDE3b3AiICsKICAgICAgInRpb25hbF91aW50NjRcMDMwXDAwNCBcMDAxKFwwMDRcMDIyXDAyN1xuXDAxN29wdGlvbmFsX3NpbnQzMlwwMzBcMDA1IiArCiAgICAgICIgXDAwMShcMDIxXDAyMlwwMjdcblwwMTdvcHRpb25hbF9zaW50NjRcMDMwXDAwNiBcMDAxKFwwMjJcMDIyXDAzMFxuXDAyMG9wdGlvbmEiICsKICAgICAgImxfZml4ZWQzMlwwMzBcMDA3IFwwMDEoXDAwN1wwMjJcMDMwXG5cMDIwb3B0aW9uYWxfZml4ZWQ2NFwwMzBcMDEwIFwwMDEoIiArCiAgICAgICJcMDA2XDAyMlwwMzFcblwwMjFvcHRpb25hbF9zZml4ZWQzMlwwMzBcdCBcMDAxKFwwMTdcMDIyXDAzMVxuXDAyMW9wdGlvbmFsIiArCiAgICAgICJfc2ZpeGVkNjRcMDMwXG4gXDAwMShcMDIwXDAyMlwwMjZcblwwMTZvcHRpb25hbF9mbG9hdFwwMzBcMDEzIFwwMDEoXDAwMlwwMjIiICsKICAgICAgIlwwMjdcblwwMTdvcHRpb25hbF9kb3VibGVcMDMwXDAxNCBcMDAxKFwwMDFcMDIyXDAyNVxuXHJvcHRpb25hbF9ib28iICsKICAgICAgImxcMDMwXHIgXDAwMShcMDEwXDAyMlwwMjdcblwwMTdvcHRpb25hbF9zdHJpbmdcMDMwXDAxNiBcMDAxKFx0XDAyMlwwMjZcblwwMTZvcHRpIiArCiAgICAgICJvbmFsX2J5dGVzXDAzMFwwMTcgXDAwMShcMDE0XDAyMkhcblxyb3B0aW9uYWxncm91cFwwMzBcMDIwIFwwMDEoXG4yIiArCiAgICAgICIxLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuT3B0IiArCiAgICAgICJpb25hbEdyb3VwXDAyMlJcblwwMjdvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZVwwMzBcMDIyICIgKwogICAgICAiXDAwMShcMDEzMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSIgKwogICAgICAiLk5lc3RlZE1lc3NhZ2VcMDIyR1xuXDAzMG9wdGlvbmFsX2ZvcmVpZ25fbWVzc2EiICsKICAgICAgImdlXDAzMFwwMjMgXDAwMShcMDEzMiUucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3MiICsKICAgICAgImFnZUxpdGVcMDIyTFxuXDAyN29wdGlvbmFsX2ltcG9ydF9tZXNzYWdlXDAzMFwwMjQgXDAwMShcMDEzIiArCiAgICAgICIyKy5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnIiArCiAgICAgICJlTGl0ZVwwMjJMXG5cMDI0b3B0aW9uYWxfbmVzdGVkX2VudW1cMDMwXDAyNSBcMDAxKFwwMTYyLi5wciIgKwogICAgICAib3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRSIgKwogICAgICAibnVtXDAyMkFcblwwMjVvcHRpb25hbF9mb3JlaWduX2VudW1cMDMwXDAyNiBcMDAxKFwwMTYyXCIucHJvIiArCiAgICAgICJ0b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGVcMDIyRlxuXDAyNG9wdGlvbiIgKwogICAgICAiYWxfaW1wb3J0X2VudW1cMDMwXDAyNyBcMDAxKFwwMTYyKC5wcm90b2J1Zl91bml0dGVzdCIgKwogICAgICAiX2ltcG9ydC5JbXBvcnRFbnVtTGl0ZVwwMjIhXG5cMDI1b3B0aW9uYWxfc3RyaW4iICsKICAgICAgImdfcGllY2VcMDMwXDAzMCBcMDAxKFx0QlwwMDJcMDEwXDAwMlwwMjJcMDMxXG5ccm9wdGlvbmFsX2NvcmRcMDMwXDAzMSBcMDAxKFx0IiArCiAgICAgICJCXDAwMlwwMTBcMDAxXDAyMllcblwwMzZvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2VcMDMwXDAzMiIgKwogICAgICAiIFwwMDEoXDAxMzIxLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJbSIgKwogICAgICAicG9ydE1lc3NhZ2VMaXRlXDAyMlRcblwwMjVvcHRpb25hbF9sYXp5X21lc3NhZ2UiICsKICAgICAgIlwwMzBcMDMzIFwwMDEoXDAxMzIxLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0wiICsKICAgICAgIml0ZS5OZXN0ZWRNZXNzYWdlQlwwMDIoXDAwMVwwMjJfXG4gb3B0aW9uYWxfdW52ZXJpIiArCiAgICAgICJmaWVkX2xhenlfbWVzc2FnZVwwMzBcMDM0IFwwMDEoXDAxMzIxLnByb3RvYnVmX3VuaXR0IiArCiAgICAgICJlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzYWdlQlwwMDJ4XDAwMVwwMjJcMDI2IiArCiAgICAgICJcblwwMTZyZXBlYXRlZF9pbnQzMlwwMzBcMDM3IFwwMDMoXDAwNVwwMjJcMDI2XG5cMDE2cmVwZWF0ZWRfaW50NjQiICsKICAgICAgIlwwMzAgIFwwMDMoXDAwM1wwMjJcMDI3XG5cMDE3cmVwZWF0ZWRfdWludDMyXDAzMCEgXDAwMyhcclwwMjJcMDI3XG5cMDE3cmVwZWEiICsKICAgICAgInRlZF91aW50NjRcMDMwXCIgXDAwMyhcMDA0XDAyMlwwMjdcblwwMTdyZXBlYXRlZF9zaW50MzJcMDMwIyBcMDAzKCIgKwogICAgICAiXDAyMVwwMjJcMDI3XG5cMDE3cmVwZWF0ZWRfc2ludDY0XDAzMCQgXDAwMyhcMDIyXDAyMlwwMzBcblwwMjByZXBlYXRlZF9mIiArCiAgICAgICJpeGVkMzJcMDMwJSBcMDAzKFwwMDdcMDIyXDAzMFxuXDAyMHJlcGVhdGVkX2ZpeGVkNjRcMDMwJiBcMDAzKFwwMDZcMDIyXDAzMSIgKwogICAgICAiXG5cMDIxcmVwZWF0ZWRfc2ZpeGVkMzJcMDMwXCcgXDAwMyhcMDE3XDAyMlwwMzFcblwwMjFyZXBlYXRlZF9zZiIgKwogICAgICAiaXhlZDY0XDAzMCggXDAwMyhcMDIwXDAyMlwwMjZcblwwMTZyZXBlYXRlZF9mbG9hdFwwMzApIFwwMDMoXDAwMlwwMjJcMDI3XG5cMDE3IiArCiAgICAgICJyZXBlYXRlZF9kb3VibGVcMDMwKiBcMDAzKFwwMDFcMDIyXDAyNVxuXHJyZXBlYXRlZF9ib29sXDAzMCsiICsKICAgICAgIiBcMDAzKFwwMTBcMDIyXDAyN1xuXDAxN3JlcGVhdGVkX3N0cmluZ1wwMzAsIFwwMDMoXHRcMDIyXDAyNlxuXDAxNnJlcGVhdGUiICsKICAgICAgImRfYnl0ZXNcMDMwLSBcMDAzKFwwMTRcMDIySFxuXHJyZXBlYXRlZGdyb3VwXDAzMC4gXDAwMyhcbjIxLnAiICsKICAgICAgInJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5SZXBlYXQiICsKICAgICAgImVkR3JvdXBcMDIyUlxuXDAyN3JlcGVhdGVkX25lc3RlZF9tZXNzYWdlXDAzMDAgXDAwMyhcMDEzIiArCiAgICAgICIyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lIiArCiAgICAgICJzdGVkTWVzc2FnZVwwMjJHXG5cMDMwcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlXDAzMCIgKwogICAgICAiMSBcMDAzKFwwMTMyJS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZSIgKwogICAgICAiTGl0ZVwwMjJMXG5cMDI3cmVwZWF0ZWRfaW1wb3J0X21lc3NhZ2VcMDMwMiBcMDAzKFwwMTMyKy4iICsKICAgICAgInByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlTGkiICsKICAgICAgInRlXDAyMkxcblwwMjRyZXBlYXRlZF9uZXN0ZWRfZW51bVwwMzAzIFwwMDMoXDAxNjIuLnByb3RvIiArCiAgICAgICJidWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtIiArCiAgICAgICJcMDIyQVxuXDAyNXJlcGVhdGVkX2ZvcmVpZ25fZW51bVwwMzA0IFwwMDMoXDAxNjJcIi5wcm90b2IiICsKICAgICAgInVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtTGl0ZVwwMjJGXG5cMDI0cmVwZWF0ZWRfIiArCiAgICAgICJpbXBvcnRfZW51bVwwMzA1IFwwMDMoXDAxNjIoLnByb3RvYnVmX3VuaXR0ZXN0X2ltIiArCiAgICAgICJwb3J0LkltcG9ydEVudW1MaXRlXDAyMiFcblwwMjVyZXBlYXRlZF9zdHJpbmdfcCIgKwogICAgICAiaWVjZVwwMzA2IFwwMDMoXHRCXDAwMlwwMTBcMDAyXDAyMlwwMzFcblxycmVwZWF0ZWRfY29yZFwwMzA3IFwwMDMoXHRCXDAwMlwwMTAiICsKICAgICAgIlwwMDFcMDIyVFxuXDAyNXJlcGVhdGVkX2xhenlfbWVzc2FnZVwwMzA5IFwwMDMoXDAxMzIxLnByb3RvIiArCiAgICAgICJidWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZXNzIiArCiAgICAgICJhZ2VCXDAwMihcMDAxXDAyMlwwMzFcblxyZGVmYXVsdF9pbnQzMlwwMzA9IFwwMDEoXDAwNTpcMDAyNDFcMDIyXDAzMVxuXHJkZSIgKwogICAgICAiZmF1bHRfaW50NjRcMDMwPiBcMDAxKFwwMDM6XDAwMjQyXDAyMlwwMzJcblwwMTZkZWZhdWx0X3VpbnQzMlwwMzAiICsKICAgICAgIj8gXDAwMShccjpcMDAyNDNcMDIyXDAzMlxuXDAxNmRlZmF1bHRfdWludDY0XDAzMEAgXDAwMShcMDA0OlwwMDI0NFwwMjJcMDMzXG4iICsKICAgICAgIlwwMTZkZWZhdWx0X3NpbnQzMlwwMzBBIFwwMDEoXDAyMTpcMDAzLTQ1XDAyMlwwMzJcblwwMTZkZWZhdWx0X3NpIiArCiAgICAgICJudDY0XDAzMEIgXDAwMShcMDIyOlwwMDI0NlwwMjJcMDMzXG5cMDE3ZGVmYXVsdF9maXhlZDMyXDAzMEMgXDAwMShcMDA3OiIgKwogICAgICAiXDAwMjQ3XDAyMlwwMzNcblwwMTdkZWZhdWx0X2ZpeGVkNjRcMDMwRCBcMDAxKFwwMDY6XDAwMjQ4XDAyMlwwMzRcblwwMjBkZWZhIiArCiAgICAgICJ1bHRfc2ZpeGVkMzJcMDMwRSBcMDAxKFwwMTc6XDAwMjQ5XDAyMlwwMzVcblwwMjBkZWZhdWx0X3NmaXhlZCIgKwogICAgICAiNjRcMDMwRiBcMDAxKFwwMjA6XDAwMy01MFwwMjJcMDMzXG5ccmRlZmF1bHRfZmxvYXRcMDMwRyBcMDAxKFwwMDI6XDAwNDUxIiArCiAgICAgICIuNVwwMjJcMDM1XG5cMDE2ZGVmYXVsdF9kb3VibGVcMDMwSCBcMDAxKFwwMDE6XDAwNTUyMDAwXDAyMlwwMzJcblwwMTRkZWYiICsKICAgICAgImF1bHRfYm9vbFwwMzBJIFwwMDEoXDAxMDpcMDA0dHJ1ZVwwMjJcMDM1XG5cMDE2ZGVmYXVsdF9zdHJpbmdcMDMwIiArCiAgICAgICJKIFwwMDEoXHQ6XDAwNWhlbGxvXDAyMlwwMzRcblxyZGVmYXVsdF9ieXRlc1wwMzBLIFwwMDEoXDAxNDpcMDA1d29yIiArCiAgICAgICJsZFwwMjJQXG5cMDIzZGVmYXVsdF9uZXN0ZWRfZW51bVwwMzBRIFwwMDEoXDAxNjIuLnByb3RvYiIgKwogICAgICAidWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRFbnVtOiIgKwogICAgICAiXDAwM0JBUlwwMjJSXG5cMDI0ZGVmYXVsdF9mb3JlaWduX2VudW1cMDMwUiBcMDAxKFwwMTYyXCIucHJvIiArCiAgICAgICJ0b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGU6XDAyMEZPUkVJR05fIiArCiAgICAgICJMSVRFX0JBUlwwMjJWXG5cMDIzZGVmYXVsdF9pbXBvcnRfZW51bVwwMzBTIFwwMDEoXDAxNjIoLiIgKwogICAgICAicHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW1MaXRlOiIgKwogICAgICAiXDAxN0lNUE9SVF9MSVRFX0JBUlwwMjIlXG5cMDI0ZGVmYXVsdF9zdHJpbmdfcGllY2UiICsKICAgICAgIlwwMzBUIFwwMDEoXHQ6XDAwM2FiY0JcMDAyXDAxMFwwMDJcMDIyXDAzNVxuXDAxNGRlZmF1bHRfY29yZFwwMzBVIFwwMDEoXHQ6XDAwMzEiICsKICAgICAgIjIzQlwwMDJcMDEwXDAwMVwwMjJcMDI2XG5cMDE0b25lb2ZfdWludDMyXDAzMG8gXDAwMShcckhcMDAwXDAyMlFcblwwMjRvbmVvZl8iICsKICAgICAgIm5lc3RlZF9tZXNzYWdlXDAzMHAgXDAwMShcMDEzMjEucHJvdG9idWZfdW5pdHRlc3QiICsKICAgICAgIi5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VIXDAwMFwwMjJcMDI2XG5cMDE0b25lIiArCiAgICAgICJvZl9zdHJpbmdcMDMwcSBcMDAxKFx0SFwwMDBcMDIyXDAyNVxuXDAxM29uZW9mX2J5dGVzXDAzMHIgXDAwMShcMDE0SFwwMDAiICsKICAgICAgIlwwMjJaXG5cMDMxb25lb2ZfbGF6eV9uZXN0ZWRfbWVzc2FnZVwwMzBzIFwwMDEoXDAxMzIxLnByIiArCiAgICAgICJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNIiArCiAgICAgICJlc3NhZ2VCXDAwMihcMDAxSFwwMDBcMDIyU1xuXDAyNW9uZW9mX25lc3RlZF9tZXNzYWdlMlwwMzB1ICIgKwogICAgICAiXDAwMShcMDEzMjIucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSIgKwogICAgICAiLk5lc3RlZE1lc3NhZ2UySFwwMDBcMDIyXDAzNlxuXDAyNmRlY2VwdGl2ZWx5X25hbWVkX2wiICsKICAgICAgImlzdFwwMzB0IFwwMDEoXDAwNVwwMzI3XG5cck5lc3RlZE1lc3NhZ2VcMDIyXG5cblwwMDJiYlwwMzBcMDAxIFwwMDEoXDAwNVwwMjJcbiIgKwogICAgICAiXG5cMDAyY2NcMDMwXDAwMiBcMDAxKFwwMDNcMDIyXDAxNlxuXDAwMmRkXDAzMFwwMDMgXDAwMyhcMDA1QlwwMDJcMDIwXDAwMVwwMzJcMDM0XG5cMDE2TmVzdGVkTWVzcyIgKwogICAgICAiYWdlMlwwMjJcblxuXDAwMmRkXDAzMFwwMDEgXDAwMShcMDA1XDAzMlwwMzJcblxyT3B0aW9uYWxHcm91cFwwMjJcdFxuXDAwMWFcMDMwXDAyMSIgKwogICAgICAiIFwwMDEoXDAwNVwwMzJcMDMyXG5cclJlcGVhdGVkR3JvdXBcMDIyXHRcblwwMDFhXDAzMC8gXDAwMShcMDA1XCJcJ1xuXG5OZXN0IiArCiAgICAgICJlZEVudW1cMDIyXDAwN1xuXDAwM0ZPT1wwMjBcMDAxXDAyMlwwMDdcblwwMDNCQVJcMDIwXDAwMlwwMjJcMDA3XG5cMDAzQkFaXDAyMFwwMDNCXHJcblwwMTNvbmUiICsKICAgICAgIm9mX2ZpZWxkXCJcMDM3XG5cMDIyRm9yZWlnbk1lc3NhZ2VMaXRlXDAyMlx0XG5cMDAxY1wwMzBcMDAxIFwwMDEoIiArCiAgICAgICJcMDA1XCJcMjYyXDAwM1xuXDAyM1Rlc3RQYWNrZWRUeXBlc0xpdGVcMDIyXDAzMFxuXDAxNHBhY2tlZF9pbnQzIiArCiAgICAgICIyXDAzMFogXDAwMyhcMDA1QlwwMDJcMDIwXDAwMVwwMjJcMDMwXG5cMDE0cGFja2VkX2ludDY0XDAzMFsgXDAwMyhcMDAzQlwwMDJcMDIwXDAwMVwwMjJcMDMxXG4iICsKICAgICAgIlxycGFja2VkX3VpbnQzMlwwMzBcXCBcMDAzKFxyQlwwMDJcMDIwXDAwMVwwMjJcMDMxXG5ccnBhY2tlZF91aW50NiIgKwogICAgICAiNFwwMzBdIFwwMDMoXDAwNEJcMDAyXDAyMFwwMDFcMDIyXDAzMVxuXHJwYWNrZWRfc2ludDMyXDAzMF4gXDAwMyhcMDIxQlwwMDJcMDIwXDAwMVwwMjJcMDMxIiArCiAgICAgICJcblxycGFja2VkX3NpbnQ2NFwwMzBfIFwwMDMoXDAyMkJcMDAyXDAyMFwwMDFcMDIyXDAzMlxuXDAxNnBhY2tlZF9maXhlIiArCiAgICAgICJkMzJcMDMwYCBcMDAzKFwwMDdCXDAwMlwwMjBcMDAxXDAyMlwwMzJcblwwMTZwYWNrZWRfZml4ZWQ2NFwwMzBhIFwwMDMoXDAwNkJcMDAyXDAyMCIgKwogICAgICAiXDAwMVwwMjJcMDMzXG5cMDE3cGFja2VkX3NmaXhlZDMyXDAzMGIgXDAwMyhcMDE3QlwwMDJcMDIwXDAwMVwwMjJcMDMzXG5cMDE3cGFja2VkIiArCiAgICAgICJfc2ZpeGVkNjRcMDMwYyBcMDAzKFwwMjBCXDAwMlwwMjBcMDAxXDAyMlwwMzBcblwwMTRwYWNrZWRfZmxvYXRcMDMwZCBcMDAzKCIgKwogICAgICAiXDAwMkJcMDAyXDAyMFwwMDFcMDIyXDAzMVxuXHJwYWNrZWRfZG91YmxlXDAzMGUgXDAwMyhcMDAxQlwwMDJcMDIwXDAwMVwwMjJcMDI3XG5cMDEzcGFjayIgKwogICAgICAiZWRfYm9vbFwwMzBmIFwwMDMoXDAxMEJcMDAyXDAyMFwwMDFcMDIyO1xuXDAxM3BhY2tlZF9lbnVtXDAzMGcgXDAwMyhcMDE2MlwiIiArCiAgICAgICIucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlQlwwMDJcMDIwXDAwMVwiISIgKwogICAgICAiXG5cMDI1VGVzdEFsbEV4dGVuc2lvbnNMaXRlKlwwMTBcMDEwXDAwMVwwMjBcMjAwXDIwMFwyMDBcMjAwXDAwMlwiKVxuXDAzNE9wdCIgKwogICAgICAiaW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZVwwMjJcdFxuXDAwMWFcMDMwXDAyMSBcMDAxKFwwMDVcIilcblwwMzQiICsKICAgICAgIlJlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVcMDIyXHRcblwwMDFhXDAzMC8gXDAwMShcMDA1XCIiICsKICAgICAgIiRcblwwMzBUZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUqXDAxMFwwMTBcMDAxXDAyMFwyMDBcMjAwXDIwMFwyMDBcMDAyXCJeXG4iICsKICAgICAgIlwwMjdUZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZTJDXG5cMDIwbmVzdGVkX2V4dGVuIiArCiAgICAgICJzaW9uXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvIiArCiAgICAgICJuc0xpdGVcMDMwXDI3MWAgXDAwMShcMDA1XCJcMjY2XDAwMVxuXDAyMlRlc3REZXByZWNhdGVkTGl0ZVwwMjJcMDM0XG5cMDIwIiArCiAgICAgICJkZXByZWNhdGVkX2ZpZWxkXDAzMFwwMDEgXDAwMShcMDA1QlwwMDJcMDMwXDAwMVwwMjJcMDM1XG5cMDIxZGVwcmVjYXRlZCIgKwogICAgICAiX2ZpZWxkMlwwMzBcMDAyIFwwMDIoXDAwNUJcMDAyXDAzMFwwMDFcMDIyXDAzNVxuXDAyMWRlcHJlY2F0ZWRfZmllbGQzXDAzMFwwMDMiICsKICAgICAgIiBcMDAxKFx0QlwwMDJcMDMwXDAwMVwwMjJEXG5cMDIxZGVwcmVjYXRlZF9maWVsZDRcMDMwXDAwNCBcMDAxKFwwMTMyJS5wciIgKwogICAgICAib3RvYnVmX3VuaXR0ZXN0LlRlc3REZXByZWNhdGVkTGl0ZUJcMDAyXDAzMFwwMDFcIlwzMTMiICsKICAgICAgIlxuXG5cMDI0VGVzdFBhcnNpbmdNZXJnZUxpdGVcMDIyP1xuXDAyMnJlcXVpcmVkX2FsbF8iICsKICAgICAgInR5cGVzXDAzMFwwMDEgXDAwMihcMDEzMiMucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFQiICsKICAgICAgInlwZXNMaXRlXDAyMj9cblwwMjJvcHRpb25hbF9hbGxfdHlwZXNcMDMwXDAwMiBcMDAxKFwwMTMyIy5wIiArCiAgICAgICJyb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGVcMDIyP1xuXDAyMnJlcCIgKwogICAgICAiZWF0ZWRfYWxsX3R5cGVzXDAzMFwwMDMgXDAwMyhcMDEzMiMucHJvdG9idWZfdW5pdHRlcyIgKwogICAgICAidC5UZXN0QWxsVHlwZXNMaXRlXDAyMkxcblxyb3B0aW9uYWxncm91cFwwMzBcbiBcMDAxKCIgKwogICAgICAiXG4yNS5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlTGkiICsKICAgICAgInRlLk9wdGlvbmFsR3JvdXBcMDIyTFxuXHJyZXBlYXRlZGdyb3VwXDAzMFwwMjQgXDAwMyhcbjIiICsKICAgICAgIjUucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGUiICsKICAgICAgIi5SZXBlYXRlZEdyb3VwXDAzMlwzMTZcMDA0XG5cMDI3UmVwZWF0ZWRGaWVsZHNHZW5lcmF0IiArCiAgICAgICJvclwwMjIzXG5cMDA2ZmllbGQxXDAzMFwwMDEgXDAwMyhcMDEzMiMucHJvdG9idWZfdW5pdHRlc3QuVCIgKwogICAgICAiZXN0QWxsVHlwZXNMaXRlXDAyMjNcblwwMDZmaWVsZDJcMDMwXDAwMiBcMDAzKFwwMTMyIy5wcm90b2IiICsKICAgICAgInVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGVcMDIyM1xuXDAwNmZpZWxkM1wwMzBcMDAzIiArCiAgICAgICIgXDAwMyhcMDEzMiMucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0IiArCiAgICAgICJlXDAyMlZcblwwMDZncm91cDFcMDMwXG4gXDAwMyhcbjJGLnByb3RvYnVmX3VuaXR0ZXN0LlRlIiArCiAgICAgICJzdFBhcnNpbmdNZXJnZUxpdGUuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0IiArCiAgICAgICJvci5Hcm91cDFcMDIyVlxuXDAwNmdyb3VwMlwwMzBcMDI0IFwwMDMoXG4yRi5wcm90b2J1Zl91bmkiICsKICAgICAgInR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2VMaXRlLlJlcGVhdGVkRmllbGQiICsKICAgICAgInNHZW5lcmF0b3IuR3JvdXAyXDAyMjJcblwwMDRleHQxXDAzMFwzNTBcMDA3IFwwMDMoXDAxMzIjLnByb3RvIiArCiAgICAgICJidWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZVwwMjIyXG5cMDA0ZXh0MlwwMzBcMzUxXDAwNyIgKwogICAgICAiIFwwMDMoXDAxMzIjLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdCIgKwogICAgICAiZVwwMzI9XG5cMDA2R3JvdXAxXDAyMjNcblwwMDZmaWVsZDFcMDMwXDAxMyBcMDAxKFwwMTMyIy5wcm90b2J1Zl91IiArCiAgICAgICJuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGVcMDMyPVxuXDAwNkdyb3VwMlwwMjIzXG5cMDA2ZmkiICsKICAgICAgImVsZDFcMDMwXDAyNSBcMDAxKFwwMTMyIy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHkiICsKICAgICAgInBlc0xpdGVcMDMyVlxuXHJPcHRpb25hbEdyb3VwXDAyMkVcblwwMzBvcHRpb25hbF9ncm8iICsKICAgICAgInVwX2FsbF90eXBlc1wwMzBcMDEzIFwwMDEoXDAxMzIjLnByb3RvYnVmX3VuaXR0ZXN0LlQiICsKICAgICAgImVzdEFsbFR5cGVzTGl0ZVwwMzJWXG5cclJlcGVhdGVkR3JvdXBcMDIyRVxuXDAzMHJlcGUiICsKICAgICAgImF0ZWRfZ3JvdXBfYWxsX3R5cGVzXDAzMFwwMjUgXDAwMShcMDEzMiMucHJvdG9idWZfdW4iICsKICAgICAgIml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlKlx0XDAxMFwzNTBcMDA3XDAyMFwyMDBcMjAwXDIwMFwyMDBcMDAyMmNcblwwMTRvcCIgKwogICAgICAidGlvbmFsX2V4dFwwMjJcJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2kiICsKICAgICAgIm5nTWVyZ2VMaXRlXDAzMFwzNTBcMDA3IFwwMDEoXDAxMzIjLnByb3RvYnVmX3VuaXR0ZXN0LlQiICsKICAgICAgImVzdEFsbFR5cGVzTGl0ZTJjXG5cMDE0cmVwZWF0ZWRfZXh0XDAyMlwnLnByb3RvYiIgKwogICAgICAidWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZUxpdGVcMDMwXDM1MVwwMDcgXDAwMyhcMDEzMiIgKwogICAgICAiIy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlXCJaXG5cMDI2IiArCiAgICAgICJUZXN0TWVyZ2VFeGNlcHRpb25MaXRlXDAyMkBcblwwMTZhbGxfZXh0ZW5zaW9ucyIgKwogICAgICAiXDAzMFwwMDEgXDAwMShcMDEzMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVucyIgKwogICAgICAiaW9uc0xpdGVcIlwwMjZcblwwMjRUZXN0RW1wdHlNZXNzYWdlTGl0ZVwiLlxuXCJUZXN0IiArCiAgICAgICJFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGUqXDAxMFwwMTBcMDAxXDAyMFwyMDBcMjAwXDIwMFwyMDBcMDAyIiArCiAgICAgICJcIl9cblxyVjFNZXNzYWdlTGl0ZVwwMjJcMDIxXG5cdGludF9maWVsZFwwMzBcMDAxIFwwMDIoXDAwNVwwMjI7XG5cbiIgKwogICAgICAiZW51bV9maWVsZFwwMzBcMDAyIFwwMDEoXDAxNjJcMDM1LnByb3RvYnVmX3VuaXR0ZXN0LlYxRSIgKwogICAgICAibnVtTGl0ZTpcMDEwVjFfRklSU1RcIl9cblxyVjJNZXNzYWdlTGl0ZVwwMjJcMDIxXG5cdGluIiArCiAgICAgICJ0X2ZpZWxkXDAzMFwwMDEgXDAwMihcMDA1XDAyMjtcblxuZW51bV9maWVsZFwwMzBcMDAyIFwwMDEoXDAxNjJcMDM1LnByb3QiICsKICAgICAgIm9idWZfdW5pdHRlc3QuVjJFbnVtTGl0ZTpcMDEwVjJfRklSU1RcIlwyMjVcMDA2XG5cMDMwVCIgKwogICAgICAiZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVcMDIyXDAzMlxuXDAxNm9wdGlvbmFsX2ludDMiICsKICAgICAgIjJcMDMwXDM2MFwzNzBcMzc3XDM3N1wwMDEgXDAwMShcMDA1XDAyMlwwMjRcblwwMTBmaXhlZF8zMlwwMzBcMzYxXDM3MFwzNzdcMzc3XDAwMSBcMDAxKFwwMDVcMDIyXDAzNlxuXDAxNnJlcCIgKwogICAgICAiZWF0ZWRfaW50MzJcMDMwXDM2MlwzNzBcMzc3XDM3N1wwMDEgXDAwMyhcMDA1QlwwMDJcMDIwXDAwMFwwMjJcMDM0XG5cMDE0cGFja2VkX2ludDMiICsKICAgICAgIjJcMDMwXDM2M1wzNzBcMzc3XDM3N1wwMDEgXDAwMyhcMDA1QlwwMDJcMDIwXDAwMVwwMjI9XG5ccm9wdGlvbmFsX2VudW1cMDMwXDM2NFwzNzBcMzc3XDM3N1wwMDEgXDAwMSIgKwogICAgICAiKFwwMTYyXCIucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1MaXRlXDAyMlwwMzMiICsKICAgICAgIlxuXDAxN29wdGlvbmFsX3N0cmluZ1wwMzBcMzY1XDM3MFwzNzdcMzc3XDAwMSBcMDAxKFx0XDAyMlwwMzJcblwwMTZvcHRpb25hbF8iICsKICAgICAgImJ5dGVzXDAzMFwzNjZcMzcwXDM3N1wzNzdcMDAxIFwwMDEoXDAxNFwwMjJDXG5cMDIwb3B0aW9uYWxfbWVzc2FnZVwwMzBcMzY3XDM3MFwzNzdcMzc3IiArCiAgICAgICJcMDAxIFwwMDEoXDAxMzIlLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlIiArCiAgICAgICJMaXRlXDAyMlRcblxyb3B0aW9uYWxncm91cFwwMzBcMzcwXDM3MFwzNzdcMzc3XDAwMSBcMDAxKFxuMjkucHJvdG9iIiArCiAgICAgICJ1Zl91bml0dGVzdC5UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGUuT3B0IiArCiAgICAgICJpb25hbEdyb3VwXDAyMl9cblwwMjFzdHJpbmdfc3RyaW5nX21hcFwwMzBcMzcyXDM3MFwzNzdcMzc3XDAwMSBcMDAzKCIgKwogICAgICAiXDAxMzJALnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RIdWdlRmllbGROdW1iZSIgKwogICAgICAicnNMaXRlLlN0cmluZ1N0cmluZ01hcEVudHJ5XDAyMlwwMzJcblwwMTRvbmVvZl91aW4iICsKICAgICAgInQzMlwwMzBcMzczXDM3MFwzNzdcMzc3XDAwMSBcMDAxKFxySFwwMDBcMDIyR1xuXDAyNG9uZW9mX3Rlc3RfYWxsX3R5cGVzXDAzMCIgKwogICAgICAiXDM3NFwzNzBcMzc3XDM3N1wwMDEgXDAwMShcMDEzMiMucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cCIgKwogICAgICAiZXNMaXRlSFwwMDBcMDIyXDAzMlxuXDAxNG9uZW9mX3N0cmluZ1wwMzBcMzc1XDM3MFwzNzdcMzc3XDAwMSBcMDAxKFx0SFwwMDBcMDIyXDAzMVxuXDAxMyIgKwogICAgICAib25lb2ZfYnl0ZXNcMDMwXDM3NlwzNzBcMzc3XDM3N1wwMDEgXDAwMShcMDE0SFwwMDBcMDMyJFxuXHJPcHRpb25hbEdyb3VwIiArCiAgICAgICJcMDIyXDAyM1xuXDAwN2dyb3VwX2FcMDMwXDM3MVwzNzBcMzc3XDM3N1wwMDEgXDAwMShcMDA1XDAzMjZcblwwMjRTdHJpbmdTdHJpbmdNYXAiICsKICAgICAgIkVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFx0XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFx0OlwwMDI4XDAwMSpcMDE0XDAxMCIgKwogICAgICAiXDM0MFwyNTJcMzc3XDM3N1wwMDFcMDIwXDM2MFwzNzBcMzc3XDM3N1wwMDFCXHJcblwwMTNvbmVvZl9maWVsZFwiXDI0NVwwMDNcblwwMjRUZXN0T25lb2YiICsKICAgICAgIlBhcnNpbmdMaXRlXDAyMlwwMjVcblwwMTNvbmVvZl9pbnQzMlwwMzBcMDAxIFwwMDEoXDAwNUhcMDAwXDAyMj9cblwwMjBvbiIgKwogICAgICAiZW9mX3N1Ym1lc3NhZ2VcMDMwXDAwMiBcMDAxKFwwMTMyIy5wcm90b2J1Zl91bml0dGVzdCIgKwogICAgICAiLlRlc3RBbGxUeXBlc0xpdGVIXDAwMFwwMjJcMDI2XG5cMDE0b25lb2Zfc3RyaW5nXDAzMFwwMDMgXDAwMSgiICsKICAgICAgIlx0SFwwMDBcMDIyJFxuXDAxM29uZW9mX2J5dGVzXDAzMFwwMDQgXDAwMShcMDE0OlxyZGVmYXVsdCBieXRlc0giICsKICAgICAgIlwwMDBcMDIyLVxuXDAyMW9uZW9mX3N0cmluZ19jb3JkXDAzMFwwMDUgXDAwMShcdDpcMDE0ZGVmYXVsdCBDbyIgKwogICAgICAicmRCXDAwMlwwMTBcMDAxSFwwMDBcMDIyXDAzNlxuXDAyMG9uZW9mX2J5dGVzX2NvcmRcMDMwXDAwNiBcMDAxKFwwMTRCXDAwMlwwMTBcMDAxSFwwMDAiICsKICAgICAgIlwwMjJcJ1xuXDAzMW9uZW9mX3N0cmluZ19zdHJpbmdfcGllY2VcMDMwXDAwNyBcMDAxKFx0QlwwMDJcMDEwXDAwMkgiICsKICAgICAgIlwwMDBcMDIyO1xuXDAzMG9uZW9mX2J5dGVzX3N0cmluZ19waWVjZVwwMzBcMDEwIFwwMDEoXDAxNDpcMDIzZGVmIiArCiAgICAgICJhdWx0IFN0cmluZ1BpZWNlQlwwMDJcMDEwXDAwMkhcMDAwXDAyMjNcblxub25lb2ZfZW51bVwwMzBcdCBcMDAxIiArCiAgICAgICIoXDAxNjJcMDM1LnByb3RvYnVmX3VuaXR0ZXN0LlYyRW51bUxpdGVIXDAwMEJcclxuXDAxM28iICsKICAgICAgIm5lb2ZfZmllbGRcIlwiXG5cMDIyVGVzdE1lc3NhZ2VTZXRMaXRlKlwwMTBcMDEwZFwwMjBcMzc3XDM3N1wzNzciICsKICAgICAgIlwzNzdcMDA3OlwwMDJcMDEwXDAwMVwiKlxuXDAxM1BhY2tlZEludDMyXDAyMlwwMzNcblwwMTZyZXBlYXRlZF9pbnQzMlwwMzAiICsKICAgICAgIlwyMDBcMDIwIFwwMDMoXDAwNUJcMDAyXDAyMFwwMDFcIilcblwwMTZOb25QYWNrZWRJbnQzMlwwMjJcMDI3XG5cMDE2cmVwZWF0ZWQiICsKICAgICAgIl9pbnQzMlwwMzBcMjAwXDAyMCBcMDAzKFwwMDVcIi5cblxyUGFja2VkRml4ZWQzMlwwMjJcMDM1XG5cMDIwcmVwZWF0IiArCiAgICAgICJlZF9maXhlZDMyXDAzMFwyMDBcMDIwIFwwMDMoXDAwN0JcMDAyXDAyMFwwMDFcIi1cblwwMjBOb25QYWNrZWRGaXhlZDMiICsKICAgICAgIjJcMDIyXDAzMVxuXDAyMHJlcGVhdGVkX2ZpeGVkMzJcMDMwXDIwMFwwMjAgXDAwMyhcMDA3XCJaXG5cMDA3RHVwRW51bVwiIiArCiAgICAgICJPXG5cMDMwVGVzdEVudW1XaXRoRHVwVmFsdWVMaXRlXDAyMlwwMTBcblwwMDRGT08xXDAyMFwwMDFcMDIyXDAxMFxuIiArCiAgICAgICJcMDA0QkFSMVwwMjBcMDAyXDAyMlwwMDdcblwwMDNCQVpcMDIwXDAwM1wwMjJcMDEwXG5cMDA0Rk9PMlwwMjBcMDAxXDAyMlwwMTBcblwwMDRCQVIyXDAyMFwwMDJcMDMyXDAwMlwwMjBcMDAxIiArCiAgICAgICJcIllcblwwMjBSZWN1cnNpdmVNZXNzYWdlXDAyMjRcblwwMDdyZWN1cnNlXDAzMFwwMDEgXDAwMShcMDEzMiMuIiArCiAgICAgICJwcm90b2J1Zl91bml0dGVzdC5SZWN1cnNpdmVNZXNzYWdlXDAyMlwwMTdcblwwMDdwYSIgKwogICAgICAieWxvYWRcMDMwXDAwMiBcMDAxKFwwMTQqU1xuXDAxN0ZvcmVpZ25FbnVtTGl0ZVwwMjJcMDI0XG5cMDIwRk9SRUlHIiArCiAgICAgICJOX0xJVEVfRk9PXDAyMFwwMDRcMDIyXDAyNFxuXDAyMEZPUkVJR05fTElURV9CQVpcMDIwXDAwNlwwMjJcMDI0XG5cMDIwRk8iICsKICAgICAgIlJFSUdOX0xJVEVfQkFSXDAyMFwwMDUqXDAzMlxuXG5WMUVudW1MaXRlXDAyMlwwMTRcblwwMTBWMV9GSVIiICsKICAgICAgIlNUXDAyMFwwMDEqKVxuXG5WMkVudW1MaXRlXDAyMlwwMTRcblwwMTBWMl9GSVJTVFwwMjBcMDAxXDAyMlxyXG5cdFYyX1MiICsKICAgICAgIkVDT05EXDAyMFwwMDI6T1xuXDAzNW9wdGlvbmFsX2ludDMyX2V4dGVuc2lvbl9saXRlIiArCiAgICAgICJcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpIiArCiAgICAgICJ0ZVwwMzBcMDAxIFwwMDEoXDAwNTpPXG5cMDM1b3B0aW9uYWxfaW50NjRfZXh0ZW5zaW9uX2xpdCIgKwogICAgICAiZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTCIgKwogICAgICAiaXRlXDAzMFwwMDIgXDAwMShcMDAzOlBcblwwMzZvcHRpb25hbF91aW50MzJfZXh0ZW5zaW9uX2wiICsKICAgICAgIml0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb24iICsKICAgICAgInNMaXRlXDAzMFwwMDMgXDAwMShccjpQXG5cMDM2b3B0aW9uYWxfdWludDY0X2V4dGVuc2lvbiIgKwogICAgICAiX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaSIgKwogICAgICAib25zTGl0ZVwwMzBcMDA0IFwwMDEoXDAwNDpQXG5cMDM2b3B0aW9uYWxfc2ludDMyX2V4dGVuc2kiICsKICAgICAgIm9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW4iICsKICAgICAgInNpb25zTGl0ZVwwMzBcMDA1IFwwMDEoXDAyMTpQXG5cMDM2b3B0aW9uYWxfc2ludDY0X2V4dGVuIiArCiAgICAgICJzaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0IiArCiAgICAgICJlbnNpb25zTGl0ZVwwMzBcMDA2IFwwMDEoXDAyMjpRXG5cMDM3b3B0aW9uYWxfZml4ZWQzMl9leCIgKwogICAgICAidGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbCIgKwogICAgICAiRXh0ZW5zaW9uc0xpdGVcMDMwXDAwNyBcMDAxKFwwMDc6UVxuXDAzN29wdGlvbmFsX2ZpeGVkNjQiICsKICAgICAgIl9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3QiICsKICAgICAgIkFsbEV4dGVuc2lvbnNMaXRlXDAzMFwwMTAgXDAwMShcMDA2OlJcbiBvcHRpb25hbF9zZml4IiArCiAgICAgICJlZDMyX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuIiArCiAgICAgICJUZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwXHQgXDAwMShcMDE3OlJcbiBvcHRpb25hbF8iICsKICAgICAgInNmaXhlZDY0X2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHQiICsKICAgICAgImVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwXG4gXDAwMShcMDIwOk9cblwwMzVvcHRpbyIgKwogICAgICAibmFsX2Zsb2F0X2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdCIgKwogICAgICAidGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwXDAxMyBcMDAxKFwwMDI6UFxuXDAzNm9wdGkiICsKICAgICAgIm9uYWxfZG91YmxlX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW4iICsKICAgICAgIml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwXDAxNCBcMDAxKFwwMDE6TlxuXDAzNG9wIiArCiAgICAgICJ0aW9uYWxfYm9vbF9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuIiArCiAgICAgICJpdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMFxyIFwwMDEoXDAxMDpQXG5cMDM2b3AiICsKICAgICAgInRpb25hbF9zdHJpbmdfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl8iICsKICAgICAgInVuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDE2IFwwMDEoXHQ6T1xuXDAzNSIgKwogICAgICAib3B0aW9uYWxfYnl0ZXNfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1ZiIgKwogICAgICAiX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDE3IFwwMDEoXDAxNDpcMTc3XG4iICsKICAgICAgIlwwMzRvcHRpb25hbGdyb3VwX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWYiICsKICAgICAgIl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwXDAyMCBcMDAxKFxuMi8uIiArCiAgICAgICJwcm90b2J1Zl91bml0dGVzdC5PcHRpb25hbEdyb3VwX2V4dGVuc2lvIiArCiAgICAgICJuX2xpdGU6XDIxM1wwMDFcbiZvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZV9leHRlbiIgKwogICAgICAic2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dCIgKwogICAgICAiZW5zaW9uc0xpdGVcMDMwXDAyMiBcMDAxKFwwMTMyMS5wcm90b2J1Zl91bml0dGVzdC5UZSIgKwogICAgICAic3RBbGxUeXBlc0xpdGUuTmVzdGVkTWVzc2FnZTpcMjAwXDAwMVxuXCdvcHRpb25hIiArCiAgICAgICJsX2ZvcmVpZ25fbWVzc2FnZV9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvIiArCiAgICAgICJidWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMFwwMjMgXDAwMShcMDEzIiArCiAgICAgICIyJS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGU6IiArCiAgICAgICJcMjA1XDAwMVxuJm9wdGlvbmFsX2ltcG9ydF9tZXNzYWdlX2V4dGVuc2lvbl9saSIgKwogICAgICAidGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucyIgKwogICAgICAiTGl0ZVwwMzBcMDI0IFwwMDEoXDAxMzIrLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbSIgKwogICAgICAicG9ydE1lc3NhZ2VMaXRlOlwyMDVcMDAxXG4jb3B0aW9uYWxfbmVzdGVkX2VudW0iICsKICAgICAgIl9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3QiICsKICAgICAgIkFsbEV4dGVuc2lvbnNMaXRlXDAzMFwwMjUgXDAwMShcMDE2Mi4ucHJvdG9idWZfdW5pdHQiICsKICAgICAgImVzdC5UZXN0QWxsVHlwZXNMaXRlLk5lc3RlZEVudW06elxuJG9wdGlvIiArCiAgICAgICJuYWxfZm9yZWlnbl9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9iIiArCiAgICAgICJ1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwXDAyNiBcMDAxKFwwMTYyIiArCiAgICAgICJcIi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUxpdGU6XDE3N1xuI28iICsKICAgICAgInB0aW9uYWxfaW1wb3J0X2VudW1fZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm8iICsKICAgICAgInRvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDI3IFwwMDEiICsKICAgICAgIihcMDE2MigucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW0iICsKICAgICAgIkxpdGU6WlxuJG9wdGlvbmFsX3N0cmluZ19waWVjZV9leHRlbnNpb25fIiArCiAgICAgICJsaXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvIiArCiAgICAgICJuc0xpdGVcMDMwXDAzMCBcMDAxKFx0QlwwMDJcMDEwXDAwMjpOXG5cMDM0b3B0aW9uYWxfY29yZF9leHRlbnMiICsKICAgICAgImlvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGUiICsKICAgICAgIm5zaW9uc0xpdGVcMDMwXDAzMSBcMDAxKFx0OlwyMjJcMDAxXG4tb3B0aW9uYWxfcHVibGljX2ltcCIgKwogICAgICAib3J0X21lc3NhZ2VfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91biIgKwogICAgICAiaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDMyIFwwMDEoXDAxMzIxLnBybyIgKwogICAgICAidG9idWZfdW5pdHRlc3RfaW1wb3J0LlB1YmxpY0ltcG9ydE1lc3NhZyIgKwogICAgICAiZUxpdGU6XDIxNVwwMDFcbiRvcHRpb25hbF9sYXp5X21lc3NhZ2VfZXh0ZW5zaW8iICsKICAgICAgIm5fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnMiICsKICAgICAgImlvbnNMaXRlXDAzMFwwMzMgXDAwMShcMDEzMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdEEiICsKICAgICAgImxsVHlwZXNMaXRlLk5lc3RlZE1lc3NhZ2VCXDAwMihcMDAxOlwyMzBcMDAxXG4vb3B0aW9uIiArCiAgICAgICJhbF91bnZlcmlmaWVkX2xhenlfbWVzc2FnZV9leHRlbnNpb25fbGl0IiArCiAgICAgICJlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMIiArCiAgICAgICJpdGVcMDMwXDAzNCBcMDAxKFwwMTMyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwIiArCiAgICAgICJlc0xpdGUuTmVzdGVkTWVzc2FnZUJcMDAyeFwwMDE6T1xuXDAzNXJlcGVhdGVkX2ludCIgKwogICAgICAiMzJfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZSIgKwogICAgICAic3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcMDM3IFwwMDMoXDAwNTpPXG5cMDM1cmVwZWF0ZWRfaW4iICsKICAgICAgInQ2NF9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlQiICsKICAgICAgImVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMCAgXDAwMyhcMDAzOlBcblwwMzZyZXBlYXRlZF91IiArCiAgICAgICJpbnQzMl9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0IiArCiAgICAgICIuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMCEgXDAwMyhccjpQXG5cMDM2cmVwZWF0ZWQiICsKICAgICAgIl91aW50NjRfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGUiICsKICAgICAgInN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBcIiBcMDAzKFwwMDQ6UFxuXDAzNnJlcGVhdCIgKwogICAgICAiZWRfc2ludDMyX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdCIgKwogICAgICAidGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwIyBcMDAzKFwwMjE6UFxuXDAzNnJlcGUiICsKICAgICAgImF0ZWRfc2ludDY0X2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW4iICsKICAgICAgIml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwJCBcMDAzKFwwMjI6UVxuXDAzN3JlIiArCiAgICAgICJwZWF0ZWRfZml4ZWQzMl9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmIiArCiAgICAgICJfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMCUgXDAwMyhcMDA3OlFcbiIgKwogICAgICAiXDAzN3JlcGVhdGVkX2ZpeGVkNjRfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90byIgKwogICAgICAiYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzAmIFwwMDMoXDAwNiIgKwogICAgICAiOlJcbiByZXBlYXRlZF9zZml4ZWQzMl9leHRlbnNpb25fbGl0ZVwwMjIoLnAiICsKICAgICAgInJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMFwnIiArCiAgICAgICIgXDAwMyhcMDE3OlJcbiByZXBlYXRlZF9zZml4ZWQ2NF9leHRlbnNpb25fbGl0ZSIgKwogICAgICAiXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaSIgKwogICAgICAidGVcMDMwKCBcMDAzKFwwMjA6T1xuXDAzNXJlcGVhdGVkX2Zsb2F0X2V4dGVuc2lvbl9saXQiICsKICAgICAgImVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0wiICsKICAgICAgIml0ZVwwMzApIFwwMDMoXDAwMjpQXG5cMDM2cmVwZWF0ZWRfZG91YmxlX2V4dGVuc2lvbl9sIiArCiAgICAgICJpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uIiArCiAgICAgICJzTGl0ZVwwMzAqIFwwMDMoXDAwMTpOXG5cMDM0cmVwZWF0ZWRfYm9vbF9leHRlbnNpb25fbCIgKwogICAgICAiaXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbiIgKwogICAgICAic0xpdGVcMDMwKyBcMDAzKFwwMTA6UFxuXDAzNnJlcGVhdGVkX3N0cmluZ19leHRlbnNpb24iICsKICAgICAgIl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2kiICsKICAgICAgIm9uc0xpdGVcMDMwLCBcMDAzKFx0Ok9cblwwMzVyZXBlYXRlZF9ieXRlc19leHRlbnNpbyIgKwogICAgICAibl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVucyIgKwogICAgICAiaW9uc0xpdGVcMDMwLSBcMDAzKFwwMTQ6XDE3N1xuXDAzNHJlcGVhdGVkZ3JvdXBfZXh0ZW5zaW8iICsKICAgICAgIm5fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnMiICsKICAgICAgImlvbnNMaXRlXDAzMC4gXDAwMyhcbjIvLnByb3RvYnVmX3VuaXR0ZXN0LlJlcGVhIiArCiAgICAgICJ0ZWRHcm91cF9leHRlbnNpb25fbGl0ZTpcMjEzXDAwMVxuJnJlcGVhdGVkX25lcyIgKwogICAgICAidGVkX21lc3NhZ2VfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91biIgKwogICAgICAiaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzAwIFwwMDMoXDAxMzIxLnBybyIgKwogICAgICAidG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZS5OZXN0ZWRNZSIgKwogICAgICAic3NhZ2U6XDIwMFwwMDFcblwncmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlX2V4dGVuIiArCiAgICAgICJzaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0IiArCiAgICAgICJlbnNpb25zTGl0ZVwwMzAxIFwwMDMoXDAxMzIlLnByb3RvYnVmX3VuaXR0ZXN0LkZvIiArCiAgICAgICJyZWlnbk1lc3NhZ2VMaXRlOlwyMDVcMDAxXG4mcmVwZWF0ZWRfaW1wb3J0X21lcyIgKwogICAgICAic2FnZV9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LiIgKwogICAgICAiVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMDIgXDAwMyhcMDEzMisucHJvdG9idWZfdSIgKwogICAgICAibml0dGVzdF9pbXBvcnQuSW1wb3J0TWVzc2FnZUxpdGU6XDIwNVwwMDFcbiNyZXAiICsKICAgICAgImVhdGVkX25lc3RlZF9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG8iICsKICAgICAgImJ1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwMyBcMDAzKFwwMTYiICsKICAgICAgIjIuLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmUiICsKICAgICAgInN0ZWRFbnVtOnpcbiRyZXBlYXRlZF9mb3JlaWduX2VudW1fZXh0ZW5zIiArCiAgICAgICJpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlIiArCiAgICAgICJuc2lvbnNMaXRlXDAzMDQgXDAwMyhcMDE2MlwiLnByb3RvYnVmX3VuaXR0ZXN0LkZvciIgKwogICAgICAiZWlnbkVudW1MaXRlOlwxNzdcbiNyZXBlYXRlZF9pbXBvcnRfZW51bV9leHQiICsKICAgICAgImVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEUiICsKICAgICAgInh0ZW5zaW9uc0xpdGVcMDMwNSBcMDAzKFwwMTYyKC5wcm90b2J1Zl91bml0dGVzdF8iICsKICAgICAgImltcG9ydC5JbXBvcnRFbnVtTGl0ZTpaXG4kcmVwZWF0ZWRfc3RyaW5nIiArCiAgICAgICJfcGllY2VfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzIiArCiAgICAgICJ0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzA2IFwwMDMoXHRCXDAwMlwwMTBcMDAyOk5cblwwMzRyZXAiICsKICAgICAgImVhdGVkX2NvcmRfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bmkiICsKICAgICAgInR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzA3IFwwMDMoXHQ6XDIxNVwwMDFcbiRyZSIgKwogICAgICAicGVhdGVkX2xhenlfbWVzc2FnZV9leHRlbnNpb25fbGl0ZVwwMjIoLnBybyIgKwogICAgICAidG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMDkgXDAwMyIgKwogICAgICAiKFwwMTMyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLiIgKwogICAgICAiTmVzdGVkTWVzc2FnZUJcMDAyKFwwMDE6UlxuXDAzNGRlZmF1bHRfaW50MzJfZXh0ZW4iICsKICAgICAgInNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHQiICsKICAgICAgImVuc2lvbnNMaXRlXDAzMD0gXDAwMShcMDA1OlwwMDI0MTpSXG5cMDM0ZGVmYXVsdF9pbnQ2NF9lIiArCiAgICAgICJ4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsIiArCiAgICAgICJsRXh0ZW5zaW9uc0xpdGVcMDMwPiBcMDAxKFwwMDM6XDAwMjQyOlNcblwwMzVkZWZhdWx0X3VpbiIgKwogICAgICAidDMyX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVCIgKwogICAgICAiZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwPyBcMDAxKFxyOlwwMDI0MzpTXG5cMDM1ZGVmYXVsIiArCiAgICAgICJ0X3VpbnQ2NF9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0IiArCiAgICAgICJlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMEAgXDAwMShcMDA0OlwwMDI0NDpUXG5cMDM1ZCIgKwogICAgICAiZWZhdWx0X3NpbnQzMl9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmXyIgKwogICAgICAidW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMEEgXDAwMShcMDIxOlwwMDMtNCIgKwogICAgICAiNTpTXG5cMDM1ZGVmYXVsdF9zaW50NjRfZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm8iICsKICAgICAgInRvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZVwwMzBCIFwwMDEiICsKICAgICAgIihcMDIyOlwwMDI0NjpUXG5cMDM2ZGVmYXVsdF9maXhlZDMyX2V4dGVuc2lvbl9saXRlIiArCiAgICAgICJcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpIiArCiAgICAgICJ0ZVwwMzBDIFwwMDEoXDAwNzpcMDAyNDc6VFxuXDAzNmRlZmF1bHRfZml4ZWQ2NF9leHRlbnNpbyIgKwogICAgICAibl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVucyIgKwogICAgICAiaW9uc0xpdGVcMDMwRCBcMDAxKFwwMDY6XDAwMjQ4OlVcblwwMzdkZWZhdWx0X3NmaXhlZDMyX2UiICsKICAgICAgInh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWwiICsKICAgICAgImxFeHRlbnNpb25zTGl0ZVwwMzBFIFwwMDEoXDAxNzpcMDAyNDk6VlxuXDAzN2RlZmF1bHRfc2ZpIiArCiAgICAgICJ4ZWQ2NF9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaXR0ZXN0IiArCiAgICAgICIuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMEYgXDAwMShcMDIwOlwwMDMtNTA6VFxuXDAzNGRlZiIgKwogICAgICAiYXVsdF9mbG9hdF9leHRlbnNpb25fbGl0ZVwwMjIoLnByb3RvYnVmX3VuaSIgKwogICAgICAidHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMEcgXDAwMShcMDAyOlwwMDQ1MS41OiIgKwogICAgICAiVlxuXDAzNWRlZmF1bHRfZG91YmxlX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG8iICsKICAgICAgImJ1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwSCBcMDAxKFwwMDEiICsKICAgICAgIjpcMDA1NTIwMDA6U1xuXDAzM2RlZmF1bHRfYm9vbF9leHRlbnNpb25fbGl0ZVwwMjIoIiArCiAgICAgICIucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlIiArCiAgICAgICJcMDMwSSBcMDAxKFwwMTA6XDAwNHRydWU6VlxuXDAzNWRlZmF1bHRfc3RyaW5nX2V4dGVuc2lvbiIgKwogICAgICAiX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaSIgKwogICAgICAib25zTGl0ZVwwMzBKIFwwMDEoXHQ6XDAwNWhlbGxvOlVcblwwMzRkZWZhdWx0X2J5dGVzX2V4IiArCiAgICAgICJ0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsIiArCiAgICAgICJFeHRlbnNpb25zTGl0ZVwwMzBLIFwwMDEoXDAxNDpcMDA1d29ybGQ6XDIxMVwwMDFcblwiZGVmYXVsdF8iICsKICAgICAgIm5lc3RlZF9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW4iICsKICAgICAgIml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwUSBcMDAxKFwwMTYyLi5wcm8iICsKICAgICAgInRvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUuTmVzdGVkRW4iICsKICAgICAgInVtOlwwMDNCQVI6XDIxM1wwMDFcbiNkZWZhdWx0X2ZvcmVpZ25fZW51bV9leHRlbnNpIiArCiAgICAgICJvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuIiArCiAgICAgICJzaW9uc0xpdGVcMDMwUiBcMDAxKFwwMTYyXCIucHJvdG9idWZfdW5pdHRlc3QuRm9yZSIgKwogICAgICAiaWduRW51bUxpdGU6XDAyMEZPUkVJR05fTElURV9CQVI6XDIxN1wwMDFcblwiZGVmYXVsIiArCiAgICAgICJ0X2ltcG9ydF9lbnVtX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfIiArCiAgICAgICJ1bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwUyBcMDAxKFwwMTYyKC5wIiArCiAgICAgICJyb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtTGl0ZTpcMDE3IiArCiAgICAgICJJTVBPUlRfTElURV9CQVI6XlxuI2RlZmF1bHRfc3RyaW5nX3BpZWNlXyIgKwogICAgICAiZXh0ZW5zaW9uX2xpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QSIgKwogICAgICAibGxFeHRlbnNpb25zTGl0ZVwwMzBUIFwwMDEoXHQ6XDAwM2FiY0JcMDAyXDAxMFwwMDI6UlxuXDAzM2RlZmF1IiArCiAgICAgICJsdF9jb3JkX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW5pdHRlIiArCiAgICAgICJzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwVSBcMDAxKFx0OlwwMDMxMjM6TVxuXDAzM28iICsKICAgICAgIm5lb2ZfdWludDMyX2V4dGVuc2lvbl9saXRlXDAyMigucHJvdG9idWZfdW4iICsKICAgICAgIml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9uc0xpdGVcMDMwbyBcMDAxKFxyOlwyMTBcMDAxXG4jbyIgKwogICAgICAibmVvZl9uZXN0ZWRfbWVzc2FnZV9leHRlbnNpb25fbGl0ZVwwMjIoLnBybyIgKwogICAgICAidG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnNMaXRlXDAzMHAgXDAwMSIgKwogICAgICAiKFwwMTMyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlLiIgKwogICAgICAiTmVzdGVkTWVzc2FnZTpNXG5cMDMzb25lb2Zfc3RyaW5nX2V4dGVuc2lvbl8iICsKICAgICAgImxpdGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW8iICsKICAgICAgIm5zTGl0ZVwwMzBxIFwwMDEoXHQ6TFxuXDAzMm9uZW9mX2J5dGVzX2V4dGVuc2lvbl9saSIgKwogICAgICAidGVcMDIyKC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucyIgKwogICAgICAiTGl0ZVwwMzByIFwwMDEoXDAxNDpUXG5cMDMzcGFja2VkX2ludDMyX2V4dGVuc2lvbl9saXQiICsKICAgICAgImVcMDIyKy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW8iICsKICAgICAgIm5zTGl0ZVwwMzBaIFwwMDMoXDAwNUJcMDAyXDAyMFwwMDE6VFxuXDAzM3BhY2tlZF9pbnQ2NF9leHRlbnNpIiArCiAgICAgICJvbl9saXRlXDAyMisucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4IiArCiAgICAgICJ0ZW5zaW9uc0xpdGVcMDMwWyBcMDAzKFwwMDNCXDAwMlwwMjBcMDAxOlVcblwwMzRwYWNrZWRfdWludDMyXyIgKwogICAgICAiZXh0ZW5zaW9uX2xpdGVcMDIyKy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UCIgKwogICAgICAiYWNrZWRFeHRlbnNpb25zTGl0ZVwwMzBcXCBcMDAzKFxyQlwwMDJcMDIwXDAwMTpVXG5cMDM0cGFja2VkXyIgKwogICAgICAidWludDY0X2V4dGVuc2lvbl9saXRlXDAyMisucHJvdG9idWZfdW5pdHRlcyIgKwogICAgICAidC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVcMDMwXSBcMDAzKFwwMDRCXDAwMlwwMjBcMDAxOlVcblwwMzQiLAogICAgICAicGFja2VkX3NpbnQzMl9leHRlbnNpb25fbGl0ZVwwMjIrLnByb3RvYnVmXyIgKwogICAgICAidW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlXDAzMF4gXDAwMyhcMDIxQiIgKwogICAgICAiXDAwMlwwMjBcMDAxOlVcblwwMzRwYWNrZWRfc2ludDY0X2V4dGVuc2lvbl9saXRlXDAyMisucHIiICsKICAgICAgIm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGUiICsKICAgICAgIlwwMzBfIFwwMDMoXDAyMkJcMDAyXDAyMFwwMDE6VlxuXDAzNXBhY2tlZF9maXhlZDMyX2V4dGVuc2lvbl9sIiArCiAgICAgICJpdGVcMDIyKy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zIiArCiAgICAgICJpb25zTGl0ZVwwMzBgIFwwMDMoXDAwN0JcMDAyXDAyMFwwMDE6VlxuXDAzNXBhY2tlZF9maXhlZDY0X2V4dCIgKwogICAgICAiZW5zaW9uX2xpdGVcMDIyKy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFjayIgKwogICAgICAiZWRFeHRlbnNpb25zTGl0ZVwwMzBhIFwwMDMoXDAwNkJcMDAyXDAyMFwwMDE6V1xuXDAzNnBhY2tlZF9zZmkiICsKICAgICAgInhlZDMyX2V4dGVuc2lvbl9saXRlXDAyMisucHJvdG9idWZfdW5pdHRlc3QiICsKICAgICAgIi5UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVcMDMwYiBcMDAzKFwwMTdCXDAwMlwwMjBcMDAxOldcblwwMzZwIiArCiAgICAgICJhY2tlZF9zZml4ZWQ2NF9leHRlbnNpb25fbGl0ZVwwMjIrLnByb3RvYnVmIiArCiAgICAgICJfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlXDAzMGMgXDAwMyhcMDIwIiArCiAgICAgICJCXDAwMlwwMjBcMDAxOlRcblwwMzNwYWNrZWRfZmxvYXRfZXh0ZW5zaW9uX2xpdGVcMDIyKy5wciIgKwogICAgICAib3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZSIgKwogICAgICAiXDAzMGQgXDAwMyhcMDAyQlwwMDJcMDIwXDAwMTpVXG5cMDM0cGFja2VkX2RvdWJsZV9leHRlbnNpb25fbGkiICsKICAgICAgInRlXDAyMisucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2kiICsKICAgICAgIm9uc0xpdGVcMDMwZSBcMDAzKFwwMDFCXDAwMlwwMjBcMDAxOlNcblwwMzJwYWNrZWRfYm9vbF9leHRlbnNpIiArCiAgICAgICJvbl9saXRlXDAyMisucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4IiArCiAgICAgICJ0ZW5zaW9uc0xpdGVcMDMwZiBcMDAzKFwwMTBCXDAwMlwwMjBcMDAxOndcblwwMzJwYWNrZWRfZW51bV9leCIgKwogICAgICAidGVuc2lvbl9saXRlXDAyMisucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhYyIgKwogICAgICAia2VkRXh0ZW5zaW9uc0xpdGVcMDMwZyBcMDAzKFwwMTYyXCIucHJvdG9idWZfdW5pdHQiICsKICAgICAgImVzdC5Gb3JlaWduRW51bUxpdGVCXDAwMlwwMjBcMDAxOnFcblwwMjN0ZXN0X2FsbF90eXBlIiArCiAgICAgICJzX2xpdGVcMDIyKy5wcm90b2J1Zl91bml0dGVzdC5UZXN0SHVnZUZpZWxkIiArCiAgICAgICJOdW1iZXJzTGl0ZVwwMzBcMzQwXDI1MlwzNzdcMzc3XDAwMSBcMDAxKFwwMTMyIy5wcm90b2J1Zl91bml0dGVzIiArCiAgICAgICJ0LlRlc3RBbGxUeXBlc0xpdGVCXDAzMlxuXDAyM2NvbS5nb29nbGUucHJvdG9idSIgKwogICAgICAiZkhcMDAzXDM3MFwwMDFcMDAxIgogICAgfTsKICAgIGRlc2NyaXB0b3IgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIC5pbnRlcm5hbEJ1aWxkR2VuZXJhdGVkRmlsZUZyb20oZGVzY3JpcHRvckRhdGEsCiAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3JbXSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5nZXREZXNjcmlwdG9yKCksCiAgICAgICAgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIk9wdGlvbmFsSW50MzIiLCAiT3B0aW9uYWxJbnQ2NCIsICJPcHRpb25hbFVpbnQzMiIsICJPcHRpb25hbFVpbnQ2NCIsICJPcHRpb25hbFNpbnQzMiIsICJPcHRpb25hbFNpbnQ2NCIsICJPcHRpb25hbEZpeGVkMzIiLCAiT3B0aW9uYWxGaXhlZDY0IiwgIk9wdGlvbmFsU2ZpeGVkMzIiLCAiT3B0aW9uYWxTZml4ZWQ2NCIsICJPcHRpb25hbEZsb2F0IiwgIk9wdGlvbmFsRG91YmxlIiwgIk9wdGlvbmFsQm9vbCIsICJPcHRpb25hbFN0cmluZyIsICJPcHRpb25hbEJ5dGVzIiwgIk9wdGlvbmFsR3JvdXAiLCAiT3B0aW9uYWxOZXN0ZWRNZXNzYWdlIiwgIk9wdGlvbmFsRm9yZWlnbk1lc3NhZ2UiLCAiT3B0aW9uYWxJbXBvcnRNZXNzYWdlIiwgIk9wdGlvbmFsTmVzdGVkRW51bSIsICJPcHRpb25hbEZvcmVpZ25FbnVtIiwgIk9wdGlvbmFsSW1wb3J0RW51bSIsICJPcHRpb25hbFN0cmluZ1BpZWNlIiwgIk9wdGlvbmFsQ29yZCIsICJPcHRpb25hbFB1YmxpY0ltcG9ydE1lc3NhZ2UiLCAiT3B0aW9uYWxMYXp5TWVzc2FnZSIsICJPcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZSIsICJSZXBlYXRlZEludDMyIiwgIlJlcGVhdGVkSW50NjQiLCAiUmVwZWF0ZWRVaW50MzIiLCAiUmVwZWF0ZWRVaW50NjQiLCAiUmVwZWF0ZWRTaW50MzIiLCAiUmVwZWF0ZWRTaW50NjQiLCAiUmVwZWF0ZWRGaXhlZDMyIiwgIlJlcGVhdGVkRml4ZWQ2NCIsICJSZXBlYXRlZFNmaXhlZDMyIiwgIlJlcGVhdGVkU2ZpeGVkNjQiLCAiUmVwZWF0ZWRGbG9hdCIsICJSZXBlYXRlZERvdWJsZSIsICJSZXBlYXRlZEJvb2wiLCAiUmVwZWF0ZWRTdHJpbmciLCAiUmVwZWF0ZWRCeXRlcyIsICJSZXBlYXRlZEdyb3VwIiwgIlJlcGVhdGVkTmVzdGVkTWVzc2FnZSIsICJSZXBlYXRlZEZvcmVpZ25NZXNzYWdlIiwgIlJlcGVhdGVkSW1wb3J0TWVzc2FnZSIsICJSZXBlYXRlZE5lc3RlZEVudW0iLCAiUmVwZWF0ZWRGb3JlaWduRW51bSIsICJSZXBlYXRlZEltcG9ydEVudW0iLCAiUmVwZWF0ZWRTdHJpbmdQaWVjZSIsICJSZXBlYXRlZENvcmQiLCAiUmVwZWF0ZWRMYXp5TWVzc2FnZSIsICJEZWZhdWx0SW50MzIiLCAiRGVmYXVsdEludDY0IiwgIkRlZmF1bHRVaW50MzIiLCAiRGVmYXVsdFVpbnQ2NCIsICJEZWZhdWx0U2ludDMyIiwgIkRlZmF1bHRTaW50NjQiLCAiRGVmYXVsdEZpeGVkMzIiLCAiRGVmYXVsdEZpeGVkNjQiLCAiRGVmYXVsdFNmaXhlZDMyIiwgIkRlZmF1bHRTZml4ZWQ2NCIsICJEZWZhdWx0RmxvYXQiLCAiRGVmYXVsdERvdWJsZSIsICJEZWZhdWx0Qm9vbCIsICJEZWZhdWx0U3RyaW5nIiwgIkRlZmF1bHRCeXRlcyIsICJEZWZhdWx0TmVzdGVkRW51bSIsICJEZWZhdWx0Rm9yZWlnbkVudW0iLCAiRGVmYXVsdEltcG9ydEVudW0iLCAiRGVmYXVsdFN0cmluZ1BpZWNlIiwgIkRlZmF1bHRDb3JkIiwgIk9uZW9mVWludDMyIiwgIk9uZW9mTmVzdGVkTWVzc2FnZSIsICJPbmVvZlN0cmluZyIsICJPbmVvZkJ5dGVzIiwgIk9uZW9mTGF6eU5lc3RlZE1lc3NhZ2UiLCAiT25lb2ZOZXN0ZWRNZXNzYWdlMiIsICJEZWNlcHRpdmVseU5hbWVkTGlzdCIsICJPbmVvZkZpZWxkIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2VfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkJiIiwgIkNjIiwgIkRkIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9OZXN0ZWRNZXNzYWdlMl9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX05lc3RlZE1lc3NhZ2UyX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfTmVzdGVkTWVzc2FnZTJfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkRkIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDIpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkEiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX1JlcGVhdGVkR3JvdXBfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsVHlwZXNMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbFR5cGVzTGl0ZV9SZXBlYXRlZEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxUeXBlc0xpdGVfUmVwZWF0ZWRHcm91cF9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiQSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJDIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhY2tlZFR5cGVzTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgyKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFja2VkVHlwZXNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYWNrZWRUeXBlc0xpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlBhY2tlZEludDMyIiwgIlBhY2tlZEludDY0IiwgIlBhY2tlZFVpbnQzMiIsICJQYWNrZWRVaW50NjQiLCAiUGFja2VkU2ludDMyIiwgIlBhY2tlZFNpbnQ2NCIsICJQYWNrZWRGaXhlZDMyIiwgIlBhY2tlZEZpeGVkNjQiLCAiUGFja2VkU2ZpeGVkMzIiLCAiUGFja2VkU2ZpeGVkNjQiLCAiUGFja2VkRmxvYXQiLCAiUGFja2VkRG91YmxlIiwgIlBhY2tlZEJvb2wiLCAiUGFja2VkRW51bSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBbGxFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgzKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QWxsRXh0ZW5zaW9uc0xpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFsbEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7IH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X09wdGlvbmFsR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoNCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfT3B0aW9uYWxHcm91cF9leHRlbnNpb25fbGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9PcHRpb25hbEdyb3VwX2V4dGVuc2lvbl9saXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJBIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUmVwZWF0ZWRHcm91cF9leHRlbnNpb25fbGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg1KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbl9saXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uX2xpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkEiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFja2VkRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoNik7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhY2tlZEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYWNrZWRFeHRlbnNpb25zTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg3KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TmVzdGVkRXh0ZW5zaW9uTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RGVwcmVjYXRlZExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoOCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdERlcHJlY2F0ZWRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3REZXByZWNhdGVkTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiRGVwcmVjYXRlZEZpZWxkIiwgIkRlcHJlY2F0ZWRGaWVsZDIiLCAiRGVwcmVjYXRlZEZpZWxkMyIsICJEZXByZWNhdGVkRmllbGQ0IiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoOSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlJlcXVpcmVkQWxsVHlwZXMiLCAiT3B0aW9uYWxBbGxUeXBlcyIsICJSZXBlYXRlZEFsbFR5cGVzIiwgIk9wdGlvbmFsR3JvdXAiLCAiUmVwZWF0ZWRHcm91cCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiRmllbGQxIiwgIkZpZWxkMiIsICJGaWVsZDMiLCAiR3JvdXAxIiwgIkdyb3VwMiIsICJFeHQxIiwgIkV4dDIiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDFfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEZpZWxkc0dlbmVyYXRvcl9Hcm91cDFfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkZpZWxkMSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMl9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3JfR3JvdXAyX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yX0dyb3VwMl9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiRmllbGQxIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfT3B0aW9uYWxHcm91cF9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJPcHRpb25hbEdyb3VwQWxsVHlwZXMiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFBhcnNpbmdNZXJnZUxpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgyKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UGFyc2luZ01lcmdlTGl0ZV9SZXBlYXRlZEdyb3VwX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RQYXJzaW5nTWVyZ2VMaXRlX1JlcGVhdGVkR3JvdXBfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlJlcGVhdGVkR3JvdXBBbGxUeXBlcyIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXJnZUV4Y2VwdGlvbkxpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXJnZUV4Y2VwdGlvbkxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lcmdlRXhjZXB0aW9uTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiQWxsRXh0ZW5zaW9ucyIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDExKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDEyKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW1wdHlNZXNzYWdlV2l0aEV4dGVuc2lvbnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbXB0eU1lc3NhZ2VXaXRoRXh0ZW5zaW9uc0xpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVjFNZXNzYWdlTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgxMyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVjFNZXNzYWdlTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMU1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJJbnRGaWVsZCIsICJFbnVtRmllbGQiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMk1lc3NhZ2VMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDE0KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9WMk1lc3NhZ2VMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1YyTWVzc2FnZUxpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkludEZpZWxkIiwgIkVudW1GaWVsZCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgxNSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiT3B0aW9uYWxJbnQzMiIsICJGaXhlZDMyIiwgIlJlcGVhdGVkSW50MzIiLCAiUGFja2VkSW50MzIiLCAiT3B0aW9uYWxFbnVtIiwgIk9wdGlvbmFsU3RyaW5nIiwgIk9wdGlvbmFsQnl0ZXMiLCAiT3B0aW9uYWxNZXNzYWdlIiwgIk9wdGlvbmFsR3JvdXAiLCAiU3RyaW5nU3RyaW5nTWFwIiwgIk9uZW9mVWludDMyIiwgIk9uZW9mVGVzdEFsbFR5cGVzIiwgIk9uZW9mU3RyaW5nIiwgIk9uZW9mQnl0ZXMiLCAiT25lb2ZGaWVsZCIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9PcHRpb25hbEdyb3VwX2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX09wdGlvbmFsR3JvdXBfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEh1Z2VGaWVsZE51bWJlcnNMaXRlX09wdGlvbmFsR3JvdXBfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkdyb3VwQSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9TdHJpbmdTdHJpbmdNYXBFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDEpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RIdWdlRmllbGROdW1iZXJzTGl0ZV9TdHJpbmdTdHJpbmdNYXBFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0SHVnZUZpZWxkTnVtYmVyc0xpdGVfU3RyaW5nU3RyaW5nTWFwRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RPbmVvZlBhcnNpbmdMaXRlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDE2KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0T25lb2ZQYXJzaW5nTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiT25lb2ZJbnQzMiIsICJPbmVvZlN1Ym1lc3NhZ2UiLCAiT25lb2ZTdHJpbmciLCAiT25lb2ZCeXRlcyIsICJPbmVvZlN0cmluZ0NvcmQiLCAiT25lb2ZCeXRlc0NvcmQiLCAiT25lb2ZTdHJpbmdTdHJpbmdQaWVjZSIsICJPbmVvZkJ5dGVzU3RyaW5nUGllY2UiLCAiT25lb2ZFbnVtIiwgIk9uZW9mRmllbGQiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZVNldExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTcpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlU2V0TGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZVNldExpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUGFja2VkSW50MzJfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTgpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1BhY2tlZEludDMyX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1BhY2tlZEludDMyX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJSZXBlYXRlZEludDMyIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfTm9uUGFja2VkSW50MzJfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMTkpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEludDMyX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJSZXBlYXRlZEludDMyIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCgyMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfUGFja2VkRml4ZWQzMl9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9QYWNrZWRGaXhlZDMyX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJSZXBlYXRlZEZpeGVkMzIiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Ob25QYWNrZWRGaXhlZDMyX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDIxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Ob25QYWNrZWRGaXhlZDMyX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X05vblBhY2tlZEZpeGVkMzJfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlJlcGVhdGVkRml4ZWQzMiIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X0R1cEVudW1fZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMjIpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X0R1cEVudW1fZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRHVwRW51bV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2Rlc2NyaXB0b3IgPQogICAgICBnZXREZXNjcmlwdG9yKCkuZ2V0TWVzc2FnZVR5cGVzKCkuZ2V0KDIzKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9SZWN1cnNpdmVNZXNzYWdlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1JlY3Vyc2l2ZU1lc3NhZ2VfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIlJlY3Vyc2UiLCAiUGF5bG9hZCIsIH0pOwogICAgb3B0aW9uYWxJbnQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgwKSk7CiAgICBvcHRpb25hbEludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDEpKTsKICAgIG9wdGlvbmFsVWludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDIpKTsKICAgIG9wdGlvbmFsVWludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDMpKTsKICAgIG9wdGlvbmFsU2ludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQpKTsKICAgIG9wdGlvbmFsU2ludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDUpKTsKICAgIG9wdGlvbmFsRml4ZWQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg2KSk7CiAgICBvcHRpb25hbEZpeGVkNjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNykpOwogICAgb3B0aW9uYWxTZml4ZWQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4KSk7CiAgICBvcHRpb25hbFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDkpKTsKICAgIG9wdGlvbmFsRmxvYXRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTApKTsKICAgIG9wdGlvbmFsRG91YmxlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDExKSk7CiAgICBvcHRpb25hbEJvb2xFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTIpKTsKICAgIG9wdGlvbmFsU3RyaW5nRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDEzKSk7CiAgICBvcHRpb25hbEJ5dGVzRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDE0KSk7CiAgICBvcHRpb25hbEdyb3VwRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDE1KSk7CiAgICBvcHRpb25hbE5lc3RlZE1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTYpKTsKICAgIG9wdGlvbmFsRm9yZWlnbk1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMTcpKTsKICAgIG9wdGlvbmFsSW1wb3J0TWVzc2FnZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgxOCkpOwogICAgb3B0aW9uYWxOZXN0ZWRFbnVtRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDE5KSk7CiAgICBvcHRpb25hbEZvcmVpZ25FbnVtRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDIwKSk7CiAgICBvcHRpb25hbEltcG9ydEVudW1FeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMjEpKTsKICAgIG9wdGlvbmFsU3RyaW5nUGllY2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMjIpKTsKICAgIG9wdGlvbmFsQ29yZEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgyMykpOwogICAgb3B0aW9uYWxQdWJsaWNJbXBvcnRNZXNzYWdlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDI0KSk7CiAgICBvcHRpb25hbExhenlNZXNzYWdlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDI1KSk7CiAgICBvcHRpb25hbFVudmVyaWZpZWRMYXp5TWVzc2FnZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgyNikpOwogICAgcmVwZWF0ZWRJbnQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgyNykpOwogICAgcmVwZWF0ZWRJbnQ2NEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgyOCkpOwogICAgcmVwZWF0ZWRVaW50MzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMjkpKTsKICAgIHJlcGVhdGVkVWludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDMwKSk7CiAgICByZXBlYXRlZFNpbnQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgzMSkpOwogICAgcmVwZWF0ZWRTaW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoMzIpKTsKICAgIHJlcGVhdGVkRml4ZWQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgzMykpOwogICAgcmVwZWF0ZWRGaXhlZDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDM0KSk7CiAgICByZXBlYXRlZFNmaXhlZDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDM1KSk7CiAgICByZXBlYXRlZFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDM2KSk7CiAgICByZXBlYXRlZEZsb2F0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDM3KSk7CiAgICByZXBlYXRlZERvdWJsZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCgzOCkpOwogICAgcmVwZWF0ZWRCb29sRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDM5KSk7CiAgICByZXBlYXRlZFN0cmluZ0V4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg0MCkpOwogICAgcmVwZWF0ZWRCeXRlc0V4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg0MSkpOwogICAgcmVwZWF0ZWRHcm91cEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg0MikpOwogICAgcmVwZWF0ZWROZXN0ZWRNZXNzYWdlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQzKSk7CiAgICByZXBlYXRlZEZvcmVpZ25NZXNzYWdlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQ0KSk7CiAgICByZXBlYXRlZEltcG9ydE1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNDUpKTsKICAgIHJlcGVhdGVkTmVzdGVkRW51bUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg0NikpOwogICAgcmVwZWF0ZWRGb3JlaWduRW51bUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg0NykpOwogICAgcmVwZWF0ZWRJbXBvcnRFbnVtRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQ4KSk7CiAgICByZXBlYXRlZFN0cmluZ1BpZWNlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDQ5KSk7CiAgICByZXBlYXRlZENvcmRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNTApKTsKICAgIHJlcGVhdGVkTGF6eU1lc3NhZ2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNTEpKTsKICAgIGRlZmF1bHRJbnQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg1MikpOwogICAgZGVmYXVsdEludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDUzKSk7CiAgICBkZWZhdWx0VWludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDU0KSk7CiAgICBkZWZhdWx0VWludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDU1KSk7CiAgICBkZWZhdWx0U2ludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDU2KSk7CiAgICBkZWZhdWx0U2ludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDU3KSk7CiAgICBkZWZhdWx0Rml4ZWQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg1OCkpOwogICAgZGVmYXVsdEZpeGVkNjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNTkpKTsKICAgIGRlZmF1bHRTZml4ZWQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg2MCkpOwogICAgZGVmYXVsdFNmaXhlZDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDYxKSk7CiAgICBkZWZhdWx0RmxvYXRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjIpKTsKICAgIGRlZmF1bHREb3VibGVFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjMpKTsKICAgIGRlZmF1bHRCb29sRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDY0KSk7CiAgICBkZWZhdWx0U3RyaW5nRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDY1KSk7CiAgICBkZWZhdWx0Qnl0ZXNFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjYpKTsKICAgIGRlZmF1bHROZXN0ZWRFbnVtRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDY3KSk7CiAgICBkZWZhdWx0Rm9yZWlnbkVudW1FeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNjgpKTsKICAgIGRlZmF1bHRJbXBvcnRFbnVtRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDY5KSk7CiAgICBkZWZhdWx0U3RyaW5nUGllY2VFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNzApKTsKICAgIGRlZmF1bHRDb3JkRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDcxKSk7CiAgICBvbmVvZlVpbnQzMkV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg3MikpOwogICAgb25lb2ZOZXN0ZWRNZXNzYWdlRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDczKSk7CiAgICBvbmVvZlN0cmluZ0V4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg3NCkpOwogICAgb25lb2ZCeXRlc0V4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg3NSkpOwogICAgcGFja2VkSW50MzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNzYpKTsKICAgIHBhY2tlZEludDY0RXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDc3KSk7CiAgICBwYWNrZWRVaW50MzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoNzgpKTsKICAgIHBhY2tlZFVpbnQ2NEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg3OSkpOwogICAgcGFja2VkU2ludDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDgwKSk7CiAgICBwYWNrZWRTaW50NjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoODEpKTsKICAgIHBhY2tlZEZpeGVkMzJFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoODIpKTsKICAgIHBhY2tlZEZpeGVkNjRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoODMpKTsKICAgIHBhY2tlZFNmaXhlZDMyRXh0ZW5zaW9uTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDg0KSk7CiAgICBwYWNrZWRTZml4ZWQ2NEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4NSkpOwogICAgcGFja2VkRmxvYXRFeHRlbnNpb25MaXRlLmludGVybmFsSW5pdChkZXNjcmlwdG9yLmdldEV4dGVuc2lvbnMoKS5nZXQoODYpKTsKICAgIHBhY2tlZERvdWJsZUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4NykpOwogICAgcGFja2VkQm9vbEV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4OCkpOwogICAgcGFja2VkRW51bUV4dGVuc2lvbkxpdGUuaW50ZXJuYWxJbml0KGRlc2NyaXB0b3IuZ2V0RXh0ZW5zaW9ucygpLmdldCg4OSkpOwogICAgdGVzdEFsbFR5cGVzTGl0ZS5pbnRlcm5hbEluaXQoZGVzY3JpcHRvci5nZXRFeHRlbnNpb25zKCkuZ2V0KDkwKSk7CiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0SW1wb3J0TGl0ZS5nZXREZXNjcmlwdG9yKCk7CiAgfQoKICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQob3V0ZXJfY2xhc3Nfc2NvcGUpCn0KUEsDBAoAAAAAAAAAIQAxNEj2nP8JAJz/CQAmAAAAcHJvdG9idWZfdW5pdHRlc3QvTWFwTGl0ZVVuaXR0ZXN0LmphdmEvLyBHZW5lcmF0ZWQgYnkgdGhlIHByb3RvY29sIGJ1ZmZlciBjb21waWxlci4gIERPIE5PVCBFRElUIQovLyBzb3VyY2U6IGdvb2dsZS9wcm90b2J1Zi9tYXBfbGl0ZV91bml0dGVzdC5wcm90bwoKLy8gUHJvdG9idWYgSmF2YSBWZXJzaW9uOiAzLjI1LjQtZGV2CnBhY2thZ2UgcHJvdG9idWZfdW5pdHRlc3Q7CgpwdWJsaWMgZmluYWwgY2xhc3MgTWFwTGl0ZVVuaXR0ZXN0IHsKICBwcml2YXRlIE1hcExpdGVVbml0dGVzdCgpIHt9CiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgcmVnaXN0cnkpIHsKICAgIHJlZ2lzdHJ5LmFkZChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5zaW5nbGUpOwogIH0KCiAgcHVibGljIHN0YXRpYyB2b2lkIHJlZ2lzdGVyQWxsRXh0ZW5zaW9ucygKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeSByZWdpc3RyeSkgewogICAgcmVnaXN0ZXJBbGxFeHRlbnNpb25zKAogICAgICAgIChjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSkgcmVnaXN0cnkpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiBlbnVtIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZX0KICAgKi8KICBwdWJsaWMgZW51bSBQcm90bzJNYXBFbnVtTGl0ZQogICAgICBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuUHJvdG9jb2xNZXNzYWdlRW51bSB7CiAgICAvKioKICAgICAqIDxjb2RlPlBST1RPMl9NQVBfRU5VTV9GT09fTElURSA9IDA7PC9jb2RlPgogICAgICovCiAgICBQUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUoMCksCiAgICAvKioKICAgICAqIDxjb2RlPlBST1RPMl9NQVBfRU5VTV9CQVJfTElURSA9IDE7PC9jb2RlPgogICAgICovCiAgICBQUk9UTzJfTUFQX0VOVU1fQkFSX0xJVEUoMSksCiAgICAvKioKICAgICAqIDxjb2RlPlBST1RPMl9NQVBfRU5VTV9CQVpfTElURSA9IDI7PC9jb2RlPgogICAgICovCiAgICBQUk9UTzJfTUFQX0VOVU1fQkFaX0xJVEUoMiksCiAgICA7CgogICAgLyoqCiAgICAgKiA8Y29kZT5QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUgPSAwOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFX1ZBTFVFID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+UFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFBST1RPMl9NQVBfRU5VTV9CQVJfTElURV9WQUxVRSA9IDE7CiAgICAvKioKICAgICAqIDxjb2RlPlBST1RPMl9NQVBfRU5VTV9CQVpfTElURSA9IDI7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBQUk9UTzJfTUFQX0VOVU1fQkFaX0xJVEVfVkFMVUUgPSAyOwoKCiAgICBwdWJsaWMgZmluYWwgaW50IGdldE51bWJlcigpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICNmb3JOdW1iZXIoaW50KX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgc3RhdGljIFByb3RvMk1hcEVudW1MaXRlIHZhbHVlT2YoaW50IHZhbHVlKSB7CiAgICAgIHJldHVybiBmb3JOdW1iZXIodmFsdWUpOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHdpcmUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZW51bSBlbnRyeS4KICAgICAqIEByZXR1cm4gVGhlIGVudW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBudW1lcmljIHdpcmUgdmFsdWUuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgUHJvdG8yTWFwRW51bUxpdGUgZm9yTnVtYmVyKGludCB2YWx1ZSkgewogICAgICBzd2l0Y2ggKHZhbHVlKSB7CiAgICAgICAgY2FzZSAwOiByZXR1cm4gUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFOwogICAgICAgIGNhc2UgMTogcmV0dXJuIFBST1RPMl9NQVBfRU5VTV9CQVJfTElURTsKICAgICAgICBjYXNlIDI6IHJldHVybiBQUk9UTzJfTUFQX0VOVU1fQkFaX0xJVEU7CiAgICAgICAgZGVmYXVsdDogcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8UHJvdG8yTWFwRW51bUxpdGU+CiAgICAgICAgaW50ZXJuYWxHZXRWYWx1ZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsVmFsdWVNYXA7CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPAogICAgICAgIFByb3RvMk1hcEVudW1MaXRlPiBpbnRlcm5hbFZhbHVlTWFwID0KICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPFByb3RvMk1hcEVudW1MaXRlPigpIHsKICAgICAgICAgICAgcHVibGljIFByb3RvMk1hcEVudW1MaXRlIGZpbmRWYWx1ZUJ5TnVtYmVyKGludCBudW1iZXIpIHsKICAgICAgICAgICAgICByZXR1cm4gUHJvdG8yTWFwRW51bUxpdGUuZm9yTnVtYmVyKG51bWJlcik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CgogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvcgogICAgICAgIGdldFZhbHVlRGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKS5nZXRWYWx1ZXMoKS5nZXQob3JkaW5hbCgpKTsKICAgIH0KICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMCk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgUHJvdG8yTWFwRW51bUxpdGVbXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICBwdWJsaWMgc3RhdGljIFByb3RvMk1hcEVudW1MaXRlIHZhbHVlT2YoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yIGRlc2MpIHsKICAgICAgaWYgKGRlc2MuZ2V0VHlwZSgpICE9IGdldERlc2NyaXB0b3IoKSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKAogICAgICAgICAgIkVudW1WYWx1ZURlc2NyaXB0b3IgaXMgbm90IGZvciB0aGlzIHR5cGUuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIFZBTFVFU1tkZXNjLmdldEluZGV4KCldOwogICAgfQoKICAgIHByaXZhdGUgZmluYWwgaW50IHZhbHVlOwoKICAgIHByaXZhdGUgUHJvdG8yTWFwRW51bUxpdGUoaW50IHZhbHVlKSB7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSkKICB9CgogIC8qKgogICAqIFByb3RvYnVmIGVudW0ge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlfQogICAqLwogIHB1YmxpYyBlbnVtIFByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlCiAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Qcm90b2NvbE1lc3NhZ2VFbnVtIHsKICAgIC8qKgogICAgICogPGNvZGU+RV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUgPSAwOzwvY29kZT4KICAgICAqLwogICAgRV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUoMCksCiAgICAvKioKICAgICAqIDxjb2RlPkVfUFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEVfUFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFKDEpLAogICAgLyoqCiAgICAgKiA8Y29kZT5FX1BST1RPMl9NQVBfRU5VTV9CQVpfTElURSA9IDI7PC9jb2RlPgogICAgICovCiAgICBFX1BST1RPMl9NQVBfRU5VTV9CQVpfTElURSgyKSwKICAgIC8qKgogICAgICogPGNvZGU+RV9QUk9UTzJfTUFQX0VOVU1fRVhUUkFfTElURSA9IDM7PC9jb2RlPgogICAgICovCiAgICBFX1BST1RPMl9NQVBfRU5VTV9FWFRSQV9MSVRFKDMpLAogICAgOwoKICAgIC8qKgogICAgICogPGNvZGU+RV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUgPSAwOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgRV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEVfVkFMVUUgPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5FX1BST1RPMl9NQVBfRU5VTV9CQVJfTElURSA9IDE7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFX1BST1RPMl9NQVBfRU5VTV9CQVJfTElURV9WQUxVRSA9IDE7CiAgICAvKioKICAgICAqIDxjb2RlPkVfUFJPVE8yX01BUF9FTlVNX0JBWl9MSVRFID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IEVfUFJPVE8yX01BUF9FTlVNX0JBWl9MSVRFX1ZBTFVFID0gMjsKICAgIC8qKgogICAgICogPGNvZGU+RV9QUk9UTzJfTUFQX0VOVU1fRVhUUkFfTElURSA9IDM7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBFX1BST1RPMl9NQVBfRU5VTV9FWFRSQV9MSVRFX1ZBTFVFID0gMzsKCgogICAgcHVibGljIGZpbmFsIGludCBnZXROdW1iZXIoKSB7CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjZm9yTnVtYmVyKGludCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIHN0YXRpYyBQcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSB2YWx1ZU9mKGludCB2YWx1ZSkgewogICAgICByZXR1cm4gZm9yTnVtYmVyKHZhbHVlKTsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgbnVtZXJpYyB3aXJlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIGVudW0gZW50cnkuCiAgICAgKiBAcmV0dXJuIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbnVtZXJpYyB3aXJlIHZhbHVlLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIFByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGZvck51bWJlcihpbnQgdmFsdWUpIHsKICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgIGNhc2UgMDogcmV0dXJuIEVfUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFOwogICAgICAgIGNhc2UgMTogcmV0dXJuIEVfUFJPVE8yX01BUF9FTlVNX0JBUl9MSVRFOwogICAgICAgIGNhc2UgMjogcmV0dXJuIEVfUFJPVE8yX01BUF9FTlVNX0JBWl9MSVRFOwogICAgICAgIGNhc2UgMzogcmV0dXJuIEVfUFJPVE8yX01BUF9FTlVNX0VYVFJBX0xJVEU7CiAgICAgICAgZGVmYXVsdDogcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8UHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICAgICAgaW50ZXJuYWxHZXRWYWx1ZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsVmFsdWVNYXA7CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPAogICAgICAgIFByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPiBpbnRlcm5hbFZhbHVlTWFwID0KICAgICAgICAgIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLkVudW1MaXRlTWFwPFByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPigpIHsKICAgICAgICAgICAgcHVibGljIFByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGZpbmRWYWx1ZUJ5TnVtYmVyKGludCBudW1iZXIpIHsKICAgICAgICAgICAgICByZXR1cm4gUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUuZm9yTnVtYmVyKG51bWJlcik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CgogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bVZhbHVlRGVzY3JpcHRvcgogICAgICAgIGdldFZhbHVlRGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKS5nZXRWYWx1ZXMoKS5nZXQob3JkaW5hbCgpKTsKICAgIH0KICAgIHB1YmxpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBnZXREZXNjcmlwdG9yKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmdldERlc2NyaXB0b3IoKS5nZXRFbnVtVHlwZXMoKS5nZXQoMSk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGVbXSBWQUxVRVMgPSB2YWx1ZXMoKTsKCiAgICBwdWJsaWMgc3RhdGljIFByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIHZhbHVlT2YoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yIGRlc2MpIHsKICAgICAgaWYgKGRlc2MuZ2V0VHlwZSgpICE9IGdldERlc2NyaXB0b3IoKSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKAogICAgICAgICAgIkVudW1WYWx1ZURlc2NyaXB0b3IgaXMgbm90IGZvciB0aGlzIHR5cGUuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIFZBTFVFU1tkZXNjLmdldEluZGV4KCldOwogICAgfQoKICAgIHByaXZhdGUgZmluYWwgaW50IHZhbHVlOwoKICAgIHByaXZhdGUgUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUoaW50IHZhbHVlKSB7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoZW51bV9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSkKICB9CgogIC8qKgogICAqIFByb3RvYnVmIGVudW0ge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcEVudW1MaXRlfQogICAqLwogIHB1YmxpYyBlbnVtIE1hcEVudW1MaXRlCiAgICAgIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5Qcm90b2NvbE1lc3NhZ2VFbnVtIHsKICAgIC8qKgogICAgICogPGNvZGU+TUFQX0VOVU1fRk9PX0xJVEUgPSAwOzwvY29kZT4KICAgICAqLwogICAgTUFQX0VOVU1fRk9PX0xJVEUoMCksCiAgICAvKioKICAgICAqIDxjb2RlPk1BUF9FTlVNX0JBUl9MSVRFID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIE1BUF9FTlVNX0JBUl9MSVRFKDEpLAogICAgLyoqCiAgICAgKiA8Y29kZT5NQVBfRU5VTV9CQVpfTElURSA9IDI7PC9jb2RlPgogICAgICovCiAgICBNQVBfRU5VTV9CQVpfTElURSgyKSwKICAgIDsKCiAgICAvKioKICAgICAqIDxjb2RlPk1BUF9FTlVNX0ZPT19MSVRFID0gMDs8L2NvZGU+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9FTlVNX0ZPT19MSVRFX1ZBTFVFID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+TUFQX0VOVU1fQkFSX0xJVEUgPSAxOzwvY29kZT4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0VOVU1fQkFSX0xJVEVfVkFMVUUgPSAxOwogICAgLyoqCiAgICAgKiA8Y29kZT5NQVBfRU5VTV9CQVpfTElURSA9IDI7PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfRU5VTV9CQVpfTElURV9WQUxVRSA9IDI7CgoKICAgIHB1YmxpYyBmaW5hbCBpbnQgZ2V0TnVtYmVyKCkgewogICAgICByZXR1cm4gdmFsdWU7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgI2Zvck51bWJlcihpbnQpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBzdGF0aWMgTWFwRW51bUxpdGUgdmFsdWVPZihpbnQgdmFsdWUpIHsKICAgICAgcmV0dXJuIGZvck51bWJlcih2YWx1ZSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWVyaWMgd2lyZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbnVtIGVudHJ5LgogICAgICogQHJldHVybiBUaGUgZW51bSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIG51bWVyaWMgd2lyZSB2YWx1ZS4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBNYXBFbnVtTGl0ZSBmb3JOdW1iZXIoaW50IHZhbHVlKSB7CiAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICBjYXNlIDA6IHJldHVybiBNQVBfRU5VTV9GT09fTElURTsKICAgICAgICBjYXNlIDE6IHJldHVybiBNQVBfRU5VTV9CQVJfTElURTsKICAgICAgICBjYXNlIDI6IHJldHVybiBNQVBfRU5VTV9CQVpfTElURTsKICAgICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5FbnVtTGl0ZU1hcDxNYXBFbnVtTGl0ZT4KICAgICAgICBpbnRlcm5hbEdldFZhbHVlTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxWYWx1ZU1hcDsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8CiAgICAgICAgTWFwRW51bUxpdGU+IGludGVybmFsVmFsdWVNYXAgPQogICAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuRW51bUxpdGVNYXA8TWFwRW51bUxpdGU+KCkgewogICAgICAgICAgICBwdWJsaWMgTWFwRW51bUxpdGUgZmluZFZhbHVlQnlOdW1iZXIoaW50IG51bWJlcikgewogICAgICAgICAgICAgIHJldHVybiBNYXBFbnVtTGl0ZS5mb3JOdW1iZXIobnVtYmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKCiAgICBwdWJsaWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtVmFsdWVEZXNjcmlwdG9yCiAgICAgICAgZ2V0VmFsdWVEZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gZ2V0RGVzY3JpcHRvcigpLmdldFZhbHVlcygpLmdldChvcmRpbmFsKCkpOwogICAgfQogICAgcHVibGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRW51bURlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIGdldERlc2NyaXB0b3IoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5FbnVtRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuZ2V0RGVzY3JpcHRvcigpLmdldEVudW1UeXBlcygpLmdldCgyKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBNYXBFbnVtTGl0ZVtdIFZBTFVFUyA9IHZhbHVlcygpOwoKICAgIHB1YmxpYyBzdGF0aWMgTWFwRW51bUxpdGUgdmFsdWVPZigKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkVudW1WYWx1ZURlc2NyaXB0b3IgZGVzYykgewogICAgICBpZiAoZGVzYy5nZXRUeXBlKCkgIT0gZ2V0RGVzY3JpcHRvcigpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAiRW51bVZhbHVlRGVzY3JpcHRvciBpcyBub3QgZm9yIHRoaXMgdHlwZS4iKTsKICAgICAgfQogICAgICByZXR1cm4gVkFMVUVTW2Rlc2MuZ2V0SW5kZXgoKV07CiAgICB9CgogICAgcHJpdmF0ZSBmaW5hbCBpbnQgdmFsdWU7CgogICAgcHJpdmF0ZSBNYXBFbnVtTGl0ZShpbnQgdmFsdWUpIHsKICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChlbnVtX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0Lk1hcEVudW1MaXRlKQogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0TWFwTGl0ZU9yQnVpbGRlciBleHRlbmRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChpbnRlcmZhY2VfZXh0ZW5kczpwcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJJbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJJbnQzMigKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJJbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwSW50MzJJbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBJbnQzMkludDMyTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJJbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMySW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQ2NEludDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBJbnQ2NEludDY0KAogICAgICAgIGxvbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50NjRJbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwSW50NjRJbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBJbnQ2NEludDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcEludDY0SW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBJbnQ2NEludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBVaW50MzJVaW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBVaW50MzJVaW50MzIoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQzMlVpbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwVWludDMyVWludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBVaW50MzJVaW50MzJNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFVpbnQzMlVpbnQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBVaW50NjRVaW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBVaW50NjRVaW50NjQoCiAgICAgICAgbG9uZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBVaW50NjRVaW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcFVpbnQ2NFVpbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwVWludDY0VWludDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBVaW50NjRVaW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwVWludDY0VWludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTaW50MzJTaW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBTaW50MzJTaW50MzIoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNpbnQzMlNpbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwU2ludDMyU2ludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBTaW50MzJTaW50MzJNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ludDMyU2ludDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTaW50NjRTaW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBTaW50NjRTaW50NjQoCiAgICAgICAgbG9uZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTaW50NjRTaW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcFNpbnQ2NFNpbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwU2ludDY0U2ludDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBTaW50NjRTaW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBGaXhlZDMyRml4ZWQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEZpeGVkNjRGaXhlZDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgIGxvbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRPclRocm93KAogICAgICAgIGxvbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwU2ZpeGVkMzJTZml4ZWQzMigKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFNmaXhlZDY0U2ZpeGVkNjQoCiAgICAgICAgbG9uZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRPclRocm93KAogICAgICAgIGxvbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMyRmxvYXRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZsb2F0KAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZsb2F0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgZ2V0TWFwSW50MzJGbG9hdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgIGdldE1hcEludDMyRmxvYXRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBmbG9hdCBnZXRNYXBJbnQzMkZsb2F0T3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgZmxvYXQgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBmbG9hdCBnZXRNYXBJbnQzMkZsb2F0T3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJEb3VibGVDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMyRG91YmxlKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkRvdWJsZU1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICBnZXRNYXBJbnQzMkRvdWJsZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgIGdldE1hcEludDMyRG91YmxlTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBkb3VibGUgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIGRvdWJsZSBnZXRNYXBJbnQzMkRvdWJsZU9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEJvb2xCb29sQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBCb29sQm9vbCgKICAgICAgICBib29sZWFuIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEJvb2xCb29sTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICBnZXRNYXBCb29sQm9vbCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICBnZXRNYXBCb29sQm9vbE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBnZXRNYXBCb29sQm9vbE9yRGVmYXVsdCgKICAgICAgICBib29sZWFuIGtleSwKICAgICAgICBib29sZWFuIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGdldE1hcEJvb2xCb29sT3JUaHJvdygKICAgICAgICBib29sZWFuIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU3RyaW5nU3RyaW5nQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFN0cmluZ1N0cmluZygKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFN0cmluZ1N0cmluZ01hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgIGdldE1hcFN0cmluZ1N0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICBnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KamF2YS5sYW5nLlN0cmluZyBnZXRNYXBTdHJpbmdTdHJpbmdPckRlZmF1bHQoCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KamF2YS5sYW5nLlN0cmluZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yVGhyb3coCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJCeXRlc0NvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMyQnl0ZXMoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyQnl0ZXNNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICBnZXRNYXBJbnQzMkJ5dGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgZ2V0TWFwSW50MzJCeXRlc01hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE1hcEludDMyQnl0ZXNPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJFbnVtQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJFbnVtKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkVudW1NYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBnZXRNYXBJbnQzMkVudW0oKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBnZXRNYXBJbnQzMkVudW1NYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlICAgICAgICAgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPgogICAgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4KICAgIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0VGVib3JpbmdDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc1RlYm9yaW5nKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRUZWJvcmluZ01hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0VGVib3JpbmcoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgdGVib3JpbmcgPSAxODs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0VGVib3JpbmdNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgdGVib3JpbmcgPSAxODs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRUZWJvcmluZ09yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFRlYm9yaW5nT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcExpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0TWFwTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwTGl0ZSkKICAgICAgVGVzdE1hcExpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RNYXBMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIFRlc3RNYXBMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdE1hcExpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdE1hcExpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgaW50IG51bWJlcikgewogICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKTsKICAgICAgICBjYXNlIDI6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCk7CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCk7CiAgICAgICAgY2FzZSA0OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCk7CiAgICAgICAgY2FzZSA1OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCk7CiAgICAgICAgY2FzZSA2OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCk7CiAgICAgICAgY2FzZSA3OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKTsKICAgICAgICBjYXNlIDg6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpOwogICAgICAgIGNhc2UgOToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKTsKICAgICAgICBjYXNlIDEwOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpOwogICAgICAgIGNhc2UgMTE6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCk7CiAgICAgICAgY2FzZSAxMjoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCk7CiAgICAgICAgY2FzZSAxMzoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCk7CiAgICAgICAgY2FzZSAxNDoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpOwogICAgICAgIGNhc2UgMTU6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCk7CiAgICAgICAgY2FzZSAxNjoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpOwogICAgICAgIGNhc2UgMTc6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCk7CiAgICAgICAgY2FzZSAxODoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldFRlYm9yaW5nKCk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICB9CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlLmNsYXNzLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0lOVDMyX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQzMkludDMyRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDApOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBJbnQzMkludDMyXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKSB7CiAgICAgIGlmIChtYXBJbnQzMkludDMyXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkludDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkludDMyKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBJbnQzMkludDMyKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJJbnQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBJbnQzMkludDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDY0X0lOVDY0X0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQ2NEludDY0RW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcEludDY0SW50NjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpIHsKICAgICAgaWYgKG1hcEludDY0SW50NjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDY0SW50NjRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBJbnQ2NEludDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDY0SW50NjQoCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQ2NEludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBJbnQ2NEludDY0KCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50NjRJbnQ2NE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBJbnQ2NEludDY0TWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBJbnQ2NEludDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBJbnQ2NEludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfVUlOVDMyX1VJTlQzMl9GSUVMRF9OVU1CRVIgPSAzOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwVWludDMyVWludDMyRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBVaW50MzJVaW50MzJFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5VSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuVUlOVDMyLAogICAgICAgICAgICAgICAgICAwKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwVWludDMyVWludDMyXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgaWYgKG1hcFVpbnQzMlVpbnQzMl8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcFVpbnQzMlVpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBVaW50MzJVaW50MzJfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBVaW50MzJVaW50MzJDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwVWludDMyVWludDMyKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQzMlVpbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwVWludDMyVWludDMyKCkgewogICAgICByZXR1cm4gZ2V0TWFwVWludDMyVWludDMyTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBVaW50MzJVaW50MzJNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBVaW50MzJVaW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfVUlOVDY0X1VJTlQ2NF9GSUVMRF9OVU1CRVIgPSA0OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBVaW50NjRVaW50NjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5VSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlVJTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBVaW50NjRVaW50NjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkgewogICAgICBpZiAobWFwVWludDY0VWludDY0XyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFVpbnQ2NFVpbnQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQ2NFVpbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBVaW50NjRVaW50NjQoCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwVWludDY0VWludDY0KCkgewogICAgICByZXR1cm4gZ2V0TWFwVWludDY0VWludDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBVaW50NjRVaW50NjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcFVpbnQ2NFVpbnQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwVWludDY0VWludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TSU5UMzJfU0lOVDMyX0ZJRUxEX05VTUJFUiA9IDU7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQzMlNpbnQzMkVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNJTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TSU5UMzIsCiAgICAgICAgICAgICAgICAgIDApOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBTaW50MzJTaW50MzJfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkgewogICAgICBpZiAobWFwU2ludDMyU2ludDMyXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU2ludDMyU2ludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFNpbnQzMlNpbnQzMl87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQzMlNpbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTaW50MzJTaW50MzIoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ludDMyU2ludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTaW50MzJTaW50MzJNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNpbnQzMlNpbnQzMk1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBTaW50MzJTaW50MzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TSU5UNjRfU0lOVDY0X0ZJRUxEX05VTUJFUiA9IDY7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQ2NFNpbnQ2NEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNJTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0lOVDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcFNpbnQ2NFNpbnQ2NF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgIGlmIChtYXBTaW50NjRTaW50NjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwU2ludDY0U2ludDY0XzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDY0U2ludDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNpbnQ2NFNpbnQ2NCgKICAgICAgICBsb25nIGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ludDY0U2ludDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTaW50NjRTaW50NjRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBTaW50NjRTaW50NjRPclRocm93KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0ZJWEVEMzJfRklYRUQzMl9GSUVMRF9OVU1CRVIgPSA3OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwRml4ZWQzMkZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkMzJGaXhlZDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRklYRUQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDMyLAogICAgICAgICAgICAgICAgICAwKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwRml4ZWQzMkZpeGVkMzJfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgIGlmIChtYXBGaXhlZDMyRml4ZWQzMl8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEZpeGVkMzJGaXhlZDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgIHJldHVybiBnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0ZJWEVENjRfRklYRUQ2NF9GSUVMRF9OVU1CRVIgPSA4OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkNjRGaXhlZDY0RW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRklYRUQ2NCwKICAgICAgICAgICAgICAgICAgMEwsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRklYRUQ2NCwKICAgICAgICAgICAgICAgICAgMEwpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBGaXhlZDY0Rml4ZWQ2NF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgaWYgKG1hcEZpeGVkNjRGaXhlZDY0XyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwRml4ZWQ2NEZpeGVkNjRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBGaXhlZDY0Rml4ZWQ2NENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBGaXhlZDY0Rml4ZWQ2NCgKICAgICAgICBsb25nIGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaXhlZDY0Rml4ZWQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwRml4ZWQ2NEZpeGVkNjQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRPclRocm93KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfU0ZJWEVEMzJfU0ZJWEVEMzJfRklFTERfTlVNQkVSID0gOTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcFNmaXhlZDMyU2ZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TRklYRUQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TRklYRUQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFNmaXhlZDMyU2ZpeGVkMzJfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpIHsKICAgICAgaWYgKG1hcFNmaXhlZDMyU2ZpeGVkMzJfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFNmaXhlZDMyU2ZpeGVkMzJfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNmaXhlZDMyU2ZpeGVkMzIoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfU0ZJWEVENjRfU0ZJWEVENjRfRklFTERfTlVNQkVSID0gMTA7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0ZJWEVENjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNGSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgaWYgKG1hcFNmaXhlZDY0U2ZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQ2NFNmaXhlZDY0KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0ZMT0FUX0ZJRUxEX05VTUJFUiA9IDExOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0Pm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZsb2F0RW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRkxPQVQsCiAgICAgICAgICAgICAgICAgIDBGKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IG1hcEludDMyRmxvYXRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+CiAgICBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKSB7CiAgICAgIGlmIChtYXBJbnQzMkZsb2F0XyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkZsb2F0XzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJGbG9hdENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJGbG9hdCgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJGbG9hdE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IGdldE1hcEludDMyRmxvYXQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQzMkZsb2F0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZ2V0TWFwSW50MzJGbG9hdE1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmbG9hdCBnZXRNYXBJbnQzMkZsb2F0T3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgZmxvYXQgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmbG9hdCBnZXRNYXBJbnQzMkZsb2F0T3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfSU5UMzJfRE9VQkxFX0ZJRUxEX05VTUJFUiA9IDEyOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkRPVUJMRSwKICAgICAgICAgICAgICAgICAgMEQpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcEludDMyRG91YmxlXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKSB7CiAgICAgIGlmIChtYXBJbnQzMkRvdWJsZV8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDMyRG91YmxlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRG91YmxlXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJEb3VibGVDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRG91YmxlKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJEb3VibGVNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gZ2V0TWFwSW50MzJEb3VibGUoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQzMkRvdWJsZU1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGdldE1hcEludDMyRG91YmxlTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGRvdWJsZSBnZXRNYXBJbnQzMkRvdWJsZU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGRvdWJsZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0JPT0xfQk9PTF9GSUVMRF9OVU1CRVIgPSAxMzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkJPT0wsCiAgICAgICAgICAgICAgICAgIGZhbHNlLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkJPT0wsCiAgICAgICAgICAgICAgICAgIGZhbHNlKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gbWFwQm9vbEJvb2xfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKSB7CiAgICAgIGlmIChtYXBCb29sQm9vbF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEJvb2xCb29sXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwQm9vbEJvb2xDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEJvb2xCb29sKAogICAgICAgIGJvb2xlYW4ga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEJvb2xCb29sTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBnZXRNYXBCb29sQm9vbCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEJvb2xCb29sTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGdldE1hcEJvb2xCb29sTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZ2V0TWFwQm9vbEJvb2xPckRlZmF1bHQoCiAgICAgICAgYm9vbGVhbiBrZXksCiAgICAgICAgYm9vbGVhbiBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBnZXRNYXBCb29sQm9vbE9yVGhyb3coCiAgICAgICAgYm9vbGVhbiBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TVFJJTkdfU1RSSU5HX0ZJRUxEX05VTUJFUiA9IDE0OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFN0cmluZ1N0cmluZ0VudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNUUklORywKICAgICAgICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU1RSSU5HLAogICAgICAgICAgICAgICAgICAiIik7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXBTdHJpbmdTdHJpbmdfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpIHsKICAgICAgaWYgKG1hcFN0cmluZ1N0cmluZ18gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcFN0cmluZ1N0cmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBTdHJpbmdTdHJpbmdfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBTdHJpbmdTdHJpbmdDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFN0cmluZ1N0cmluZygKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSkgewogICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0TWFwU3RyaW5nU3RyaW5nKCkgewogICAgICByZXR1cm4gZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IGdldE1hcFN0cmluZ1N0cmluZ01hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yRGVmYXVsdCgKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewogICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRNYXBTdHJpbmdTdHJpbmdPclRocm93KAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9CWVRFU19GSUVMRF9OVU1CRVIgPSAxNTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyQnl0ZXNEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJCeXRlc0VudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkJZVEVTLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcuRU1QVFkpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwSW50MzJCeXRlc187CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpIHsKICAgICAgaWYgKG1hcEludDMyQnl0ZXNfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyQnl0ZXNfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMkJ5dGVzQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkJ5dGVzKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkJ5dGVzTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZ2V0TWFwSW50MzJCeXRlcygpIHsKICAgICAgcmV0dXJuIGdldE1hcEludDMyQnl0ZXNNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBnZXRNYXBJbnQzMkJ5dGVzTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE1hcEludDMyQnl0ZXNPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9FTlVNX0ZJRUxEX05VTUJFUiA9IDE2OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJFbnVtRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkVudW1FbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5FTlVNLAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUuTUFQX0VOVU1fRk9PX0xJVEUuZ2V0TnVtYmVyKCkpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBJbnQzMkVudW1fOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkgewogICAgICBpZiAobWFwSW50MzJFbnVtXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJFbnVtRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRW51bV87CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPiBtYXBJbnQzMkVudW1WYWx1ZUNvbnZlcnRlciA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5uZXdFbnVtQ29udmVydGVyKAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlLmludGVybmFsR2V0VmFsdWVNYXAoKSwKICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZS5NQVBfRU5VTV9GT09fTElURSk7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBpbnRlcm5hbEdldEFkYXB0ZWRNYXBJbnQzMkVudW1NYXAoCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCkgewogICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlcjwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUsIGphdmEubGFuZy5JbnRlZ2VyPigKICAgICAgICAgICAgICBtYXAsIG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyKTsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJFbnVtQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRW51bSgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkVudW1NYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgZ2V0TWFwSW50MzJFbnVtKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJFbnVtTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZT4KICAgIGdldE1hcEludDMyRW51bU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCkpO30KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGdldE1hcEludDMyRW51bU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpCiAgICAgICAgICAgICA/IG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGdldE1hcEludDMyRW51bU9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0ZPUkVJR05fTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAxNzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJGb3JlaWduTWVzc2FnZUVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLk1FU1NBR0UsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPgogICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICBpZiAobWFwSW50MzJGb3JlaWduTWVzc2FnZV8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50MzJGb3JlaWduTWVzc2FnZV87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgVEVCT1JJTkdfRklFTERfTlVNQkVSID0gMTg7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBUZWJvcmluZ0RlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfVGVib3JpbmdFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHRlYm9yaW5nXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldFRlYm9yaW5nKCkgewogICAgICBpZiAodGVib3JpbmdfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBUZWJvcmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiB0ZWJvcmluZ187CiAgICB9CiAgICBwdWJsaWMgaW50IGdldFRlYm9yaW5nQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNUZWJvcmluZygKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldFRlYm9yaW5nTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRUZWJvcmluZygpIHsKICAgICAgcmV0dXJuIGdldFRlYm9yaW5nTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldFRlYm9yaW5nTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRUZWJvcmluZ09yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFRlYm9yaW5nT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0VGVib3JpbmcoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLAogICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplTG9uZ01hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCksCiAgICAgICAgICBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDIpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLAogICAgICAgICAgTWFwVWludDMyVWludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDMpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLAogICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDQpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLAogICAgICAgICAgTWFwU2ludDMyU2ludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDUpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLAogICAgICAgICAgTWFwU2ludDY0U2ludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDYpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCksCiAgICAgICAgICBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICA3KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplTG9uZ01hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLAogICAgICAgICAgTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgOCk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLAogICAgICAgICAgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICA5KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplTG9uZ01hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCksCiAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEwKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCksCiAgICAgICAgICBNYXBJbnQzMkZsb2F0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDExKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLAogICAgICAgICAgTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTIpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVCb29sZWFuTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCksCiAgICAgICAgICBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxMyk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZVN0cmluZ01hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKSwKICAgICAgICAgIE1hcFN0cmluZ1N0cmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxNCk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLAogICAgICAgICAgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxNSk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCksCiAgICAgICAgICBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTYpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSwKICAgICAgICAgIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTcpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldFRlYm9yaW5nKCksCiAgICAgICAgICBUZWJvcmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxOCk7CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcEludDMySW50MzJfXyA9IE1hcEludDMySW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEsIG1hcEludDMySW50MzJfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBJbnQ2NEludDY0X18gPSBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyLCBtYXBJbnQ2NEludDY0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBtYXBVaW50MzJVaW50MzJfXyA9IE1hcFVpbnQzMlVpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMywgbWFwVWludDMyVWludDMyX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBVaW50NjRVaW50NjRfXyA9IE1hcFVpbnQ2NFVpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNCwgbWFwVWludDY0VWludDY0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBtYXBTaW50MzJTaW50MzJfXyA9IE1hcFNpbnQzMlNpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNSwgbWFwU2ludDMyU2ludDMyX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBTaW50NjRTaW50NjRfXyA9IE1hcFNpbnQ2NFNpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNiwgbWFwU2ludDY0U2ludDY0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcEZpeGVkMzJGaXhlZDMyX18gPSBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNywgbWFwRml4ZWQzMkZpeGVkMzJfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgbWFwRml4ZWQ2NEZpeGVkNjRfXyA9IE1hcEZpeGVkNjRGaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg4LCBtYXBGaXhlZDY0Rml4ZWQ2NF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcFNmaXhlZDMyU2ZpeGVkMzJfXyA9IE1hcFNmaXhlZDMyU2ZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDksIG1hcFNmaXhlZDMyU2ZpeGVkMzJfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBTZml4ZWQ2NFNmaXhlZDY0X18gPSBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMCwgbWFwU2ZpeGVkNjRTZml4ZWQ2NF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgbWFwSW50MzJGbG9hdF9fID0gTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTEsIG1hcEludDMyRmxvYXRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPgogICAgICAgIG1hcEludDMyRG91YmxlX18gPSBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTIsIG1hcEludDMyRG91YmxlX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgIG1hcEJvb2xCb29sX18gPSBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTMsIG1hcEJvb2xCb29sX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgIG1hcFN0cmluZ1N0cmluZ19fID0gTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxNCwgbWFwU3RyaW5nU3RyaW5nX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgICAgICBtYXBJbnQzMkJ5dGVzX18gPSBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxNSwgbWFwSW50MzJCeXRlc19fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgbWFwSW50MzJFbnVtX18gPSBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE2LCBtYXBJbnQzMkVudW1fXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPgogICAgICAgIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfXyA9IE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE3LCBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIHRlYm9yaW5nX18gPSBUZWJvcmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTgsIHRlYm9yaW5nX18pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIG90aGVyID0gKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMySW50MzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDY0SW50NjQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwQm9vbEJvb2woKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRW51bSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0VGVib3JpbmcoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldFRlYm9yaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UMzJfSU5UMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UNjRfSU5UNjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9VSU5UMzJfVUlOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9VSU5UNjRfVUlOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9TSU5UMzJfU0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9TSU5UNjRfU0lOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0ZJWEVEMzJfRklYRUQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0ZJWEVENjRfRklYRUQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfU0ZJWEVEMzJfU0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfU0ZJWEVENjRfU0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UMzJfRkxPQVRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0RPVUJMRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0JPT0xfQk9PTF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9TVFJJTkdfU1RSSU5HX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UMzJfQllURVNfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQzMl9FTlVNX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmhhc2hDb2RlKCk7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UMzJfRk9SRUlHTl9NRVNTQUdFX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIFRFQk9SSU5HX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldFRlYm9yaW5nKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBwYXJzZUZyb20oYnl0ZVtdIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcExpdGV9CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgQnVpbGRlciBleHRlbmRzCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjxCdWlsZGVyPiBpbXBsZW1lbnRzCiAgICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwTGl0ZSkKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InJhd3R5cGVzIn0pCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkUmVmbGVjdGlvbkFjY2Vzc29yIGludGVybmFsR2V0TWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKTsKICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpOwogICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKTsKICAgICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCk7CiAgICAgICAgICBjYXNlIDU6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpOwogICAgICAgICAgY2FzZSA2OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKTsKICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKTsKICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKTsKICAgICAgICAgIGNhc2UgOToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgICAgICAgY2FzZSAxMDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpOwogICAgICAgICAgY2FzZSAxMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpOwogICAgICAgICAgY2FzZSAxMjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKTsKICAgICAgICAgIGNhc2UgMTM6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCk7CiAgICAgICAgICBjYXNlIDE0OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKTsKICAgICAgICAgIGNhc2UgMTU6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKTsKICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpOwogICAgICAgICAgY2FzZSAxNzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpOwogICAgICAgICAgY2FzZSAxODoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VGVib3JpbmcoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCk7CiAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCk7CiAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKTsKICAgICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpOwogICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCk7CiAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKTsKICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpOwogICAgICAgICAgY2FzZSA5OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgICAgICAgY2FzZSAxMDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKTsKICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCk7CiAgICAgICAgICBjYXNlIDEyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKTsKICAgICAgICAgIGNhc2UgMTM6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpOwogICAgICAgICAgY2FzZSAxNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpOwogICAgICAgICAgY2FzZSAxNToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKTsKICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKTsKICAgICAgICAgIGNhc2UgMTc6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCk7CiAgICAgICAgICBjYXNlIDE4OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlLmNsYXNzLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVUZWJvcmluZygpLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIGJ1aWxkKCkgewogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHJlc3VsdCA9IG5ldyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJJbnQzMl8gPSBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKTsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwSW50NjRJbnQ2NF8gPSBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQ2NEludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwVWludDMyVWludDMyXyA9IGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCk7CiAgICAgICAgICByZXN1bHQubWFwVWludDMyVWludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDgpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwVWludDY0VWludDY0XyA9IGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCk7CiAgICAgICAgICByZXN1bHQubWFwVWludDY0VWludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMTApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwU2ludDMyU2ludDMyXyA9IGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCk7CiAgICAgICAgICByZXN1bHQubWFwU2ludDMyU2ludDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMjApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwU2ludDY0U2ludDY0XyA9IGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCk7CiAgICAgICAgICByZXN1bHQubWFwU2ludDY0U2ludDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwNDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwRml4ZWQzMkZpeGVkMzJfID0gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpOwogICAgICAgICAgcmVzdWx0Lm1hcEZpeGVkMzJGaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwODApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwRml4ZWQ2NEZpeGVkNjRfID0gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpOwogICAgICAgICAgcmVzdWx0Lm1hcEZpeGVkNjRGaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAxMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwU2ZpeGVkMzJTZml4ZWQzMl8gPSBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTZml4ZWQzMlNmaXhlZDMyXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAyMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwU2ZpeGVkNjRTZml4ZWQ2NF8gPSBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTZml4ZWQ2NFNmaXhlZDY0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDA0MDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJGbG9hdF8gPSBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkZsb2F0Xy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDA4MDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJEb3VibGVfID0gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMyRG91YmxlXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDEwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwQm9vbEJvb2xfID0gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpOwogICAgICAgICAgcmVzdWx0Lm1hcEJvb2xCb29sXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDIwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwU3RyaW5nU3RyaW5nXyA9IGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCk7CiAgICAgICAgICByZXN1bHQubWFwU3RyaW5nU3RyaW5nXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDQwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJCeXRlc18gPSBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKTsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkJ5dGVzXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDgwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJFbnVtXyA9IGludGVybmFsR2V0TWFwSW50MzJFbnVtKCk7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJFbnVtXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMTAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJGb3JlaWduTWVzc2FnZV8gPSBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5idWlsZChNYXBJbnQzMkZvcmVpZ25NZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMjAwMDApICE9IDApKSB7CiAgICAgICAgICByZXN1bHQudGVib3JpbmdfID0gaW50ZXJuYWxHZXRUZWJvcmluZygpOwogICAgICAgICAgcmVzdWx0LnRlYm9yaW5nXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20ocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDY0SW50NjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEJvb2xCb29sKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMTAwMDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0VGVib3JpbmcoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDIwMDAwOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwSW50MzJJbnQzMl9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkludDMyX18uZ2V0S2V5KCksIG1hcEludDMySW50MzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMAogICAgICAgICAgICAgIGNhc2UgMTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwSW50NjRJbnQ2NF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50NjRJbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQ2NEludDY0X18uZ2V0S2V5KCksIG1hcEludDY0SW50NjRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxOAogICAgICAgICAgICAgIGNhc2UgMjY6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwVWludDMyVWludDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBVaW50MzJVaW50MzJfXy5nZXRLZXkoKSwgbWFwVWludDMyVWludDMyX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjYKICAgICAgICAgICAgICBjYXNlIDM0OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgICAgICAgIG1hcFVpbnQ2NFVpbnQ2NF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwVWludDY0VWludDY0X18uZ2V0S2V5KCksIG1hcFVpbnQ2NFVpbnQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM0CiAgICAgICAgICAgICAgY2FzZSA0MjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBtYXBTaW50MzJTaW50MzJfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcFNpbnQzMlNpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNpbnQzMlNpbnQzMl9fLmdldEtleSgpLCBtYXBTaW50MzJTaW50MzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0MgogICAgICAgICAgICAgIGNhc2UgNTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwU2ludDY0U2ludDY0X18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBTaW50NjRTaW50NjRfXy5nZXRLZXkoKSwgbWFwU2ludDY0U2ludDY0X18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTAKICAgICAgICAgICAgICBjYXNlIDU4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIG1hcEZpeGVkMzJGaXhlZDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwRml4ZWQzMkZpeGVkMzJfXy5nZXRLZXkoKSwgbWFwRml4ZWQzMkZpeGVkMzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1OAogICAgICAgICAgICAgIGNhc2UgNjY6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwRml4ZWQ2NEZpeGVkNjRfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcEZpeGVkNjRGaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBGaXhlZDY0Rml4ZWQ2NF9fLmdldEtleSgpLCBtYXBGaXhlZDY0Rml4ZWQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDY2CiAgICAgICAgICAgICAgY2FzZSA3NDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBtYXBTZml4ZWQzMlNmaXhlZDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNmaXhlZDMyU2ZpeGVkMzJfXy5nZXRLZXkoKSwgbWFwU2ZpeGVkMzJTZml4ZWQzMl9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc0CiAgICAgICAgICAgICAgY2FzZSA4MjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICAgICAgICBtYXBTZml4ZWQ2NFNmaXhlZDY0X18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNmaXhlZDY0U2ZpeGVkNjRfXy5nZXRLZXkoKSwgbWFwU2ZpeGVkNjRTZml4ZWQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgyCiAgICAgICAgICAgICAgY2FzZSA5MDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgICAgICAgICAgICAgbWFwSW50MzJGbG9hdF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkZsb2F0X18uZ2V0S2V5KCksIG1hcEludDMyRmxvYXRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA5MAogICAgICAgICAgICAgIGNhc2UgOTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgICAgICAgICBtYXBJbnQzMkRvdWJsZV9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEludDMyRG91YmxlX18uZ2V0S2V5KCksIG1hcEludDMyRG91YmxlX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTgKICAgICAgICAgICAgICBjYXNlIDEwNjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICAgICAgICAgICAgICBtYXBCb29sQm9vbF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwQm9vbEJvb2xEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEJvb2xCb29sX18uZ2V0S2V5KCksIG1hcEJvb2xCb29sX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTA2CiAgICAgICAgICAgICAgY2FzZSAxMTQ6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgICAgICAgICAgICAgIG1hcFN0cmluZ1N0cmluZ19fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwU3RyaW5nU3RyaW5nX18uZ2V0S2V5KCksIG1hcFN0cmluZ1N0cmluZ19fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDExNAogICAgICAgICAgICAgIGNhc2UgMTIyOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICAgICAgICAgICAgICBtYXBJbnQzMkJ5dGVzX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEludDMyQnl0ZXNfXy5nZXRLZXkoKSwgbWFwSW50MzJCeXRlc19fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEyMgogICAgICAgICAgICAgIGNhc2UgMTMwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnl0ZXMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwSW50MzJFbnVtX18gPSBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKS5wYXJzZUZyb20oYnl0ZXMpOwogICAgICAgICAgICAgICAgaWYgKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZS5mb3JOdW1iZXIobWFwSW50MzJFbnVtX18uZ2V0VmFsdWUoKSkgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25MZW5ndGhEZWxpbWl0ZWRGaWVsZCgxNiwgYnl0ZXMpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICAgIG1hcEludDMyRW51bV9fLmdldEtleSgpLCBtYXBJbnQzMkVudW1fXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEzMAogICAgICAgICAgICAgIGNhc2UgMTM4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+CiAgICAgICAgICAgICAgICBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfXy5nZXRLZXkoKSwgbWFwSW50MzJGb3JlaWduTWVzc2FnZV9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEzOAogICAgICAgICAgICAgIGNhc2UgMTQ2OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIHRlYm9yaW5nX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBUZWJvcmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVUZWJvcmluZygpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgdGVib3JpbmdfXy5nZXRLZXkoKSwgdGVib3JpbmdfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAyMDAwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxNDYKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBJbnQzMkludDMyXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpIHsKICAgICAgICBpZiAobWFwSW50MzJJbnQzMl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQzMkludDMyXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpIHsKICAgICAgICBpZiAobWFwSW50MzJJbnQzMl8gPT0gbnVsbCkgewogICAgICAgICAgbWFwSW50MzJJbnQzMl8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMySW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBJbnQzMkludDMyXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwSW50MzJJbnQzMl8gPSBtYXBJbnQzMkludDMyXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwSW50MzJJbnQzMl87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkludDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJJbnQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMySW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwSW50MzJJbnQzMigpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwSW50MzJJbnQzMk1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBJbnQzMkludDMyTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgbWFwX2ludDMyX2ludDMyID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJJbnQzMk9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEludDMySW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJJbnQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEludDMySW50MzIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEludDMySW50MzIoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEludDMySW50MzIoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJJbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcEludDY0SW50NjRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkgewogICAgICAgIGlmIChtYXBJbnQ2NEludDY0XyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDY0SW50NjRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkgewogICAgICAgIGlmIChtYXBJbnQ2NEludDY0XyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBJbnQ2NEludDY0XyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50NjRJbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEludDY0SW50NjRfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBJbnQ2NEludDY0XyA9IG1hcEludDY0SW50NjRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBJbnQ2NEludDY0XzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDY0SW50NjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQ2NEludDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDY0SW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwSW50NjRJbnQ2NCgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwSW50NjRJbnQ2NE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBJbnQ2NEludDY0TWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcEludDY0SW50NjRPckRlZmF1bHQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBJbnQ2NEludDY0T3JUaHJvdygKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwSW50NjRJbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBJbnQ2NEludDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEludDY0SW50NjQoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEludDY0SW50NjQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwSW50NjRJbnQ2NCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwVWludDMyVWludDMyXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkgewogICAgICAgIGlmIChtYXBVaW50MzJVaW50MzJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwVWludDMyVWludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBVaW50MzJVaW50MzJfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKSB7CiAgICAgICAgaWYgKG1hcFVpbnQzMlVpbnQzMl8gPT0gbnVsbCkgewogICAgICAgICAgbWFwVWludDMyVWludDMyXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwVWludDMyVWludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwVWludDMyVWludDMyXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwVWludDMyVWludDMyXyA9IG1hcFVpbnQzMlVpbnQzMl8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcFVpbnQzMlVpbnQzMl87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBVaW50MzJVaW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBVaW50MzJVaW50MzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQzMlVpbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBVaW50MzJVaW50MzIoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcFVpbnQzMlVpbnQzMk1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwVWludDMyVWludDMyTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwNCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBVaW50MzJVaW50MzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwVWludDMyVWludDMyKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBVaW50MzJVaW50MzIoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwVWludDY0VWludDY0XzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkgewogICAgICAgIGlmIChtYXBVaW50NjRVaW50NjRfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBVaW50NjRVaW50NjRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKSB7CiAgICAgICAgaWYgKG1hcFVpbnQ2NFVpbnQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgbWFwVWludDY0VWludDY0XyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwVWludDY0VWludDY0Xy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwVWludDY0VWludDY0XyA9IG1hcFVpbnQ2NFVpbnQ2NF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcFVpbnQ2NFVpbnQ2NF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBVaW50NjRVaW50NjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBVaW50NjRVaW50NjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBVaW50NjRVaW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwVWludDY0VWludDY0KCkgewogICAgICAgIHJldHVybiBnZXRNYXBVaW50NjRVaW50NjRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBVaW50NjRVaW50NjRPckRlZmF1bHQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3VpbnQ2NCwgdWludDY0Jmd0OyBtYXBfdWludDY0X3VpbnQ2NCA9IDQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBVaW50NjRVaW50NjRPclRocm93KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcFVpbnQ2NFVpbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwOCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBVaW50NjRVaW50NjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcFVpbnQ2NFVpbnQ2NCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBVaW50NjRVaW50NjQoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDg7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwU2ludDMyU2ludDMyXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkgewogICAgICAgIGlmIChtYXBTaW50MzJTaW50MzJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU2ludDMyU2ludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBTaW50MzJTaW50MzJfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgICAgaWYgKG1hcFNpbnQzMlNpbnQzMl8gPT0gbnVsbCkgewogICAgICAgICAgbWFwU2ludDMyU2ludDMyXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU2ludDMyU2ludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwU2ludDMyU2ludDMyXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwU2ludDMyU2ludDMyXyA9IG1hcFNpbnQzMlNpbnQzMl8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcFNpbnQzMlNpbnQzMl87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBTaW50MzJTaW50MzJDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTaW50MzJTaW50MzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNpbnQzMlNpbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcFNpbnQzMlNpbnQzMk1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwU2ludDMyU2ludDMyTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcFNpbnQzMlNpbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAxMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBTaW50MzJTaW50MzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQzMlNpbnQzMigpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwU2ludDMyU2ludDMyKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDEwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBTaW50MzJTaW50MzIoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMTA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwU2ludDY0U2ludDY0XzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkgewogICAgICAgIGlmIChtYXBTaW50NjRTaW50NjRfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU2ludDY0U2ludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBTaW50NjRTaW50NjRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgICAgaWYgKG1hcFNpbnQ2NFNpbnQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgbWFwU2ludDY0U2ludDY0XyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU2ludDY0U2ludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwU2ludDY0U2ludDY0Xy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwU2ludDY0U2ludDY0XyA9IG1hcFNpbnQ2NFNpbnQ2NF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcFNpbnQ2NFNpbnQ2NF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBTaW50NjRTaW50NjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTaW50NjRTaW50NjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTaW50NjRTaW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ludDY0U2ludDY0KCkgewogICAgICAgIHJldHVybiBnZXRNYXBTaW50NjRTaW50NjRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBTaW50NjRTaW50NjRPckRlZmF1bHQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NpbnQ2NCwgc2ludDY0Jmd0OyBtYXBfc2ludDY0X3NpbnQ2NCA9IDY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBTaW50NjRTaW50NjRPclRocm93KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcFNpbnQ2NFNpbnQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAyMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBTaW50NjRTaW50NjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcFNpbnQ2NFNpbnQ2NCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDIwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBTaW50NjRTaW50NjQoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwRml4ZWQzMkZpeGVkMzJfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpIHsKICAgICAgICBpZiAobWFwRml4ZWQzMkZpeGVkMzJfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwRml4ZWQzMkZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEZpeGVkMzJGaXhlZDMyXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgICAgaWYgKG1hcEZpeGVkMzJGaXhlZDMyXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBGaXhlZDMyRml4ZWQzMl8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwRml4ZWQzMkZpeGVkMzJfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBGaXhlZDMyRml4ZWQzMl8gPSBtYXBGaXhlZDMyRml4ZWQzMl8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEZpeGVkMzJGaXhlZDMyXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwRml4ZWQzMkZpeGVkMzJNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwRml4ZWQzMkZpeGVkMzJNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwNDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEZpeGVkMzJGaXhlZDMyKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBGaXhlZDMyRml4ZWQzMigKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDQwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcEZpeGVkNjRGaXhlZDY0XzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKSB7CiAgICAgICAgaWYgKG1hcEZpeGVkNjRGaXhlZDY0XyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEZpeGVkNjRGaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBGaXhlZDY0Rml4ZWQ2NF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkgewogICAgICAgIGlmIChtYXBGaXhlZDY0Rml4ZWQ2NF8gPT0gbnVsbCkgewogICAgICAgICAgbWFwRml4ZWQ2NEZpeGVkNjRfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEZpeGVkNjRGaXhlZDY0Xy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwRml4ZWQ2NEZpeGVkNjRfID0gbWFwRml4ZWQ2NEZpeGVkNjRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBGaXhlZDY0Rml4ZWQ2NF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBGaXhlZDY0Rml4ZWQ2NENvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaXhlZDY0Rml4ZWQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yRGVmYXVsdCgKICAgICAgICAgIGxvbmcga2V5LAogICAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcEZpeGVkNjRGaXhlZDY0T3JUaHJvdygKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEZpeGVkNjRGaXhlZDY0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDgwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgIGdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwODA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwRml4ZWQ2NEZpeGVkNjQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwRml4ZWQ2NEZpeGVkNjQoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA4MDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBTZml4ZWQzMlNmaXhlZDMyXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpIHsKICAgICAgICBpZiAobWFwU2ZpeGVkMzJTZml4ZWQzMl8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBTZml4ZWQzMlNmaXhlZDMyXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpIHsKICAgICAgICBpZiAobWFwU2ZpeGVkMzJTZml4ZWQzMl8gPT0gbnVsbCkgewogICAgICAgICAgbWFwU2ZpeGVkMzJTZml4ZWQzMl8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFNmaXhlZDMyU2ZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBTZml4ZWQzMlNmaXhlZDMyXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwU2ZpeGVkMzJTZml4ZWQzMl8gPSBtYXBTZml4ZWQzMlNmaXhlZDMyXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDEwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwU2ZpeGVkMzJTZml4ZWQzMl87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU2ZpeGVkMzJTZml4ZWQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNmaXhlZDMyU2ZpeGVkMzJNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDMyLCBzZml4ZWQzMiZndDsgbWFwX3NmaXhlZDMyX3NmaXhlZDMyID0gOTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAxMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwU2ZpeGVkMzJTZml4ZWQzMigKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcFNmaXhlZDMyU2ZpeGVkMzIoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgaW50IHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcFNmaXhlZDMyU2ZpeGVkMzIoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkgewogICAgICAgIGlmIChtYXBTZml4ZWQ2NFNmaXhlZDY0XyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFNmaXhlZDY0U2ZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkgewogICAgICAgIGlmIChtYXBTZml4ZWQ2NFNmaXhlZDY0XyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBTZml4ZWQ2NFNmaXhlZDY0XyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU2ZpeGVkNjRTZml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcFNmaXhlZDY0U2ZpeGVkNjRfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBTZml4ZWQ2NFNmaXhlZDY0XyA9IG1hcFNmaXhlZDY0U2ZpeGVkNjRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBTZml4ZWQ2NFNmaXhlZDY0XzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU2ZpeGVkNjRTZml4ZWQ2NCgKICAgICAgICAgIGxvbmcga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkNjQsIHNmaXhlZDY0Jmd0OyBtYXBfc2ZpeGVkNjRfc2ZpeGVkNjQgPSAxMDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBsb25nIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRPckRlZmF1bHQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGxvbmcgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE9yVGhyb3coCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcFNmaXhlZDY0U2ZpeGVkNjQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAyMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcFNmaXhlZDY0U2ZpeGVkNjQoCiAgICAgICAgICBsb25nIGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcFNmaXhlZDY0U2ZpeGVkNjQoCiAgICAgICAgICBsb25nIGtleSwKICAgICAgICAgIGxvbmcgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAyMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcFNmaXhlZDY0U2ZpeGVkNjQoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBtYXBJbnQzMkZsb2F0XzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKSB7CiAgICAgICAgaWYgKG1hcEludDMyRmxvYXRfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJGbG9hdF87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkgewogICAgICAgIGlmIChtYXBJbnQzMkZsb2F0XyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBJbnQzMkZsb2F0XyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcEludDMyRmxvYXRfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBJbnQzMkZsb2F0XyA9IG1hcEludDMyRmxvYXRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBJbnQzMkZsb2F0XzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDMyRmxvYXRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJGbG9hdCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRmxvYXRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IGdldE1hcEludDMyRmxvYXQoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEludDMyRmxvYXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBnZXRNYXBJbnQzMkZsb2F0TWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmxvYXQgZ2V0TWFwSW50MzJGbG9hdE9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBmbG9hdCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZsb2F0IGdldE1hcEludDMyRmxvYXRPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQzMkZsb2F0KCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwNDAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBJbnQzMkZsb2F0KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEludDMyRmxvYXQoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBJbnQzMkZsb2F0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGZsb2F0IHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQzMkZsb2F0KAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA0MDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXBJbnQzMkRvdWJsZV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKSB7CiAgICAgICAgaWYgKG1hcEludDMyRG91YmxlXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMyRG91YmxlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQzMkRvdWJsZV87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKSB7CiAgICAgICAgaWYgKG1hcEludDMyRG91YmxlXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBJbnQzMkRvdWJsZV8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcEludDMyRG91YmxlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwSW50MzJEb3VibGVfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBtYXBJbnQzMkRvdWJsZV8gPSBtYXBJbnQzMkRvdWJsZV8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDMyRG91YmxlXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDMyRG91YmxlQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRG91YmxlKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRG91YmxlTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gZ2V0TWFwSW50MzJEb3VibGUoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEludDMyRG91YmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gZ2V0TWFwSW50MzJEb3VibGVNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgZG91YmxlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGRvdWJsZSBnZXRNYXBJbnQzMkRvdWJsZU9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwSW50MzJEb3VibGUoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDA4MDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEludDMyRG91YmxlKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpLmdldE11dGFibGVNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBJbnQzMkRvdWJsZSgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBkb3VibGUgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwODAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEludDMyRG91YmxlKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXBCb29sQm9vbF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkgewogICAgICAgIGlmIChtYXBCb29sQm9vbF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwQm9vbEJvb2xfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpIHsKICAgICAgICBpZiAobWFwQm9vbEJvb2xfID09IG51bGwpIHsKICAgICAgICAgIG1hcEJvb2xCb29sXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwQm9vbEJvb2xEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFtYXBCb29sQm9vbF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEJvb2xCb29sXyA9IG1hcEJvb2xCb29sXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gbWFwQm9vbEJvb2xfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwQm9vbEJvb2xDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwQm9vbEJvb2woCiAgICAgICAgICBib29sZWFuIGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEJvb2xCb29sTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGdldE1hcEJvb2xCb29sKCkgewogICAgICAgIHJldHVybiBnZXRNYXBCb29sQm9vbE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBnZXRNYXBCb29sQm9vbE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gZ2V0TWFwQm9vbEJvb2xPckRlZmF1bHQoCiAgICAgICAgICBib29sZWFuIGtleSwKICAgICAgICAgIGJvb2xlYW4gZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gZ2V0TWFwQm9vbEJvb2xPclRocm93KAogICAgICAgICAgYm9vbGVhbiBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwQm9vbEJvb2woKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDEwMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEJvb2xCb29sKAogICAgICAgICAgYm9vbGVhbiBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgICAgICAgIGdldE11dGFibGVNYXBCb29sQm9vbCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEJvb2xCb29sKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEJvb2xCb29sKAogICAgICAgICAgYm9vbGVhbiBrZXksCiAgICAgICAgICBib29sZWFuIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMTAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBCb29sQm9vbCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAxMDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBtYXBTdHJpbmdTdHJpbmdfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgICAgICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkgewogICAgICAgIGlmIChtYXBTdHJpbmdTdHJpbmdfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBTdHJpbmdTdHJpbmdfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkgewogICAgICAgIGlmIChtYXBTdHJpbmdTdHJpbmdfID09IG51bGwpIHsKICAgICAgICAgIG1hcFN0cmluZ1N0cmluZ18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIE1hcFN0cmluZ1N0cmluZ0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIW1hcFN0cmluZ1N0cmluZ18uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcFN0cmluZ1N0cmluZ18gPSBtYXBTdHJpbmdTdHJpbmdfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBTdHJpbmdTdHJpbmdfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwU3RyaW5nU3RyaW5nQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFN0cmluZ1N0cmluZygKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBnZXRNYXBTdHJpbmdTdHJpbmcoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcFN0cmluZ1N0cmluZ01hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yRGVmYXVsdCgKICAgICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KamF2YS5sYW5nLlN0cmluZyBkZWZhdWx0VmFsdWUpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS5sYW5nLlN0cmluZyBnZXRNYXBTdHJpbmdTdHJpbmdPclRocm93KAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcFN0cmluZ1N0cmluZygpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMjAwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwU3RyaW5nU3RyaW5nKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgICBpZiAoa2V5ID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAga2V5Iik7IH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTdHJpbmdTdHJpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwU3RyaW5nU3RyaW5nKAogICAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXksCiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIHZhbHVlKSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAgdmFsdWUiKTsgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMjAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcFN0cmluZ1N0cmluZygKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDIwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG1hcEludDMyQnl0ZXNfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpIHsKICAgICAgICBpZiAobWFwSW50MzJCeXRlc18gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQzMkJ5dGVzXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKSB7CiAgICAgICAgaWYgKG1hcEludDMyQnl0ZXNfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMyQnl0ZXNfID0gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5uZXdNYXBGaWVsZCgKICAgICAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwSW50MzJCeXRlc18uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIG1hcEludDMyQnl0ZXNfID0gbWFwSW50MzJCeXRlc18uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDMyQnl0ZXNfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJCeXRlc0NvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkJ5dGVzKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJCeXRlc01hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZ2V0TWFwSW50MzJCeXRlcygpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwSW50MzJCeXRlc01hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IGdldE1hcEludDMyQnl0ZXNNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0TWFwSW50MzJCeXRlc09yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0TWFwSW50MzJCeXRlc09yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck1hcEludDMyQnl0ZXMoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDQwMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEludDMyQnl0ZXMoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5nZXRNdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEludDMyQnl0ZXMoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIHZhbHVlKSB7CgogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIHZhbHVlIik7IH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCB2YWx1ZSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQzMkJ5dGVzKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkJ5dGVzKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDQwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwSW50MzJFbnVtXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkgewogICAgICAgIGlmIChtYXBJbnQzMkVudW1fID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJFbnVtRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQzMkVudW1fOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKSB7CiAgICAgICAgaWYgKG1hcEludDMyRW51bV8gPT0gbnVsbCkgewogICAgICAgICAgbWFwSW50MzJFbnVtXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgTWFwSW50MzJFbnVtRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghbWFwSW50MzJFbnVtXy5pc011dGFibGUoKSkgewogICAgICAgICAgbWFwSW50MzJFbnVtXyA9IG1hcEludDMyRW51bV8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDMyRW51bV87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMkVudW1Db3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkVudW0oCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRW51bU1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZT4KICAgICAgZ2V0TWFwSW50MzJFbnVtKCkgewogICAgICAgIHJldHVybiBnZXRNYXBJbnQzMkVudW1NYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgICBnZXRNYXBJbnQzMkVudW1NYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKSk7fQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGdldE1hcEludDMyRW51bU9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgICA/IG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwSW50MzJFbnVtKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDA4MDAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZU1hcEludDMyRW51bSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgICAgICAgZ2V0TXV0YWJsZU1hcEludDMyRW51bSgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmdldE11dGFibGVNYXAoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEludDMyRW51bSgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9CYWNrd2FyZCh2YWx1ZSkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsTWFwSW50MzJFbnVtKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPiB2YWx1ZXMpIHsKICAgICAgICBpbnRlcm5hbEdldEFkYXB0ZWRNYXBJbnQzMkVudW1NYXAoCiAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmdldE11dGFibGVNYXAoKSkKICAgICAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDgwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIgaW1wbGVtZW50cyBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlci5Db252ZXJ0ZXI8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiB7CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgYnVpbGQoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyIHZhbCkgewogICAgICAgICAgaWYgKHZhbCBpbnN0YW5jZW9mIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSkgeyByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSkgdmFsOyB9CiAgICAgICAgICByZXR1cm4gKChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlcikgdmFsKS5idWlsZCgpOwogICAgICAgIH0KCiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGRlZmF1bHRFbnRyeSgpIHsKICAgICAgICAgIHJldHVybiBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIgbWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlciA9IG5ldyBNYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyKCk7CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlcj4gbWFwSW50MzJGb3JlaWduTWVzc2FnZV87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlcj4KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgICBpZiAobWFwSW50MzJGb3JlaWduTWVzc2FnZV8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjw+KG1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJGb3JlaWduTWVzc2FnZV87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgICBpZiAobWFwSW50MzJGb3JlaWduTWVzc2FnZV8gPT0gbnVsbCkgewogICAgICAgICAgbWFwSW50MzJGb3JlaWduTWVzc2FnZV8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8PihtYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4gZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldEltbXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZU9yQnVpbGRlcj4gbWFwID0gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyLmJ1aWxkKG1hcC5nZXQoa2V5KSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZSBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiBtYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyLmJ1aWxkKG1hcC5nZXQoa2V5KSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDEwMDAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZU1lc3NhZ2VNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUgdmFsdWUpIHsKCiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAgdmFsdWUiKTsgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMTAwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGU+IHZhbHVlcykgewogICAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlPiBlIDogdmFsdWVzLmVudHJ5U2V0KCkpIHsKICAgICAgICAgIGlmIChlLmdldEtleSgpID09IG51bGwgfHwgZS5nZXRWYWx1ZSgpID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5CdWlsZGVyIHB1dE1hcEludDMyRm9yZWlnbk1lc3NhZ2VCdWlsZGVySWZBYnNlbnQoCiAgICAgICAgICBpbnQga2V5KSB7CiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlT3JCdWlsZGVyPiBidWlsZGVyTWFwID0gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGVPckJ1aWxkZXIgZW50cnkgPSBidWlsZGVyTWFwLmdldChrZXkpOwogICAgICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgICAgICBlbnRyeSA9IGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLkZvcmVpZ25NZXNzYWdlTGl0ZS5uZXdCdWlsZGVyKCk7CiAgICAgICAgICBidWlsZGVyTWFwLnB1dChrZXksIGVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKGVudHJ5IGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlKSB7CiAgICAgICAgICBlbnRyeSA9ICgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuRm9yZWlnbk1lc3NhZ2VMaXRlKSBlbnRyeSkudG9CdWlsZGVyKCk7CiAgICAgICAgICBidWlsZGVyTWFwLnB1dChrZXksIGVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5Gb3JlaWduTWVzc2FnZUxpdGUuQnVpbGRlcikgZW50cnk7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdGVib3JpbmdfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRUZWJvcmluZygpIHsKICAgICAgICBpZiAodGVib3JpbmdfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgVGVib3JpbmdEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRlYm9yaW5nXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKSB7CiAgICAgICAgaWYgKHRlYm9yaW5nXyA9PSBudWxsKSB7CiAgICAgICAgICB0ZWJvcmluZ18gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIFRlYm9yaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghdGVib3JpbmdfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICB0ZWJvcmluZ18gPSB0ZWJvcmluZ18uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRlYm9yaW5nXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldFRlYm9yaW5nQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VGVib3JpbmcoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc1RlYm9yaW5nKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldFRlYm9yaW5nTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldFRlYm9yaW5nKCkgewogICAgICAgIHJldHVybiBnZXRUZWJvcmluZ01hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRUZWJvcmluZ01hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRUZWJvcmluZygpLmdldE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRUZWJvcmluZ09yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRUZWJvcmluZ09yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldFRlYm9yaW5nKCkuZ2V0TWFwKCk7CiAgICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclRlYm9yaW5nKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDIwMDAwKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVUZWJvcmluZygpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBpbnQzMiZndDsgdGVib3JpbmcgPSAxODs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVUZWJvcmluZygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGdldE11dGFibGVUZWJvcmluZygpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZVRlYm9yaW5nKCkuZ2V0TXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyB0ZWJvcmluZyA9IDE4OzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dFRlYm9yaW5nKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGludCB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHZhbHVlKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMjAwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IHRlYm9yaW5nID0gMTg7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsVGVib3JpbmcoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVGVib3JpbmcoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAyMDAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcExpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1hcExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWFwTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0TWFwTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RNYXBMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE1hcExpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE1hcExpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RBcmVuYU1hcExpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJJbnQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJJbnQzMigKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJJbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwSW50MzJJbnQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBJbnQzMkludDMyTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJJbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMySW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQ2NEludDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBJbnQ2NEludDY0KAogICAgICAgIGxvbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50NjRJbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwSW50NjRJbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBJbnQ2NEludDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcEludDY0SW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50NjQsIGludDY0Jmd0OyBtYXBfaW50NjRfaW50NjQgPSAyOzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBJbnQ2NEludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBVaW50MzJVaW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBVaW50MzJVaW50MzIoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQzMlVpbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwVWludDMyVWludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBVaW50MzJVaW50MzJNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50MzIsIHVpbnQzMiZndDsgbWFwX3VpbnQzMl91aW50MzIgPSAzOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFVpbnQzMlVpbnQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBVaW50NjRVaW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBVaW50NjRVaW50NjQoCiAgICAgICAgbG9uZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBVaW50NjRVaW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcFVpbnQ2NFVpbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwVWludDY0VWludDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBVaW50NjRVaW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwVWludDY0VWludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTaW50MzJTaW50MzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBTaW50MzJTaW50MzIoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNpbnQzMlNpbnQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwU2ludDMyU2ludDMyKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBTaW50MzJTaW50MzJNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ludDMyU2ludDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50MzIsIHNpbnQzMiZndDsgbWFwX3NpbnQzMl9zaW50MzIgPSA1OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBTaW50NjRTaW50NjRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBTaW50NjRTaW50NjQoCiAgICAgICAgbG9uZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTaW50NjRTaW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcFNpbnQ2NFNpbnQ2NCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwU2ludDY0U2ludDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBTaW50NjRTaW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBGaXhlZDMyRml4ZWQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGdldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEZpeGVkNjRGaXhlZDY0Q291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgIGxvbmcga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGdldE1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkNjQsIGZpeGVkNjQmZ3Q7IG1hcF9maXhlZDY0X2ZpeGVkNjQgPSA4OzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIGxvbmcgZ2V0TWFwRml4ZWQ2NEZpeGVkNjRPclRocm93KAogICAgICAgIGxvbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMkNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwU2ZpeGVkMzJTZml4ZWQzMigKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFNmaXhlZDY0U2ZpeGVkNjQoCiAgICAgICAgbG9uZyBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0TWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgbG9uZyBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBsb25nIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRPclRocm93KAogICAgICAgIGxvbmcga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEludDMyRmxvYXRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZsb2F0KAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZsb2F0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgZ2V0TWFwSW50MzJGbG9hdCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGZsb2F0Jmd0OyBtYXBfaW50MzJfZmxvYXQgPSAxMTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgIGdldE1hcEludDMyRmxvYXRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBmbG9hdCBnZXRNYXBJbnQzMkZsb2F0T3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgZmxvYXQgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBmbG9hdCBnZXRNYXBJbnQzMkZsb2F0T3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJEb3VibGVDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMyRG91YmxlKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkRvdWJsZU1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICBnZXRNYXBJbnQzMkRvdWJsZSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkRvdWJsZT4KICAgIGdldE1hcEludDMyRG91YmxlTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBkb3VibGUgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIGRvdWJsZSBnZXRNYXBJbnQzMkRvdWJsZU9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEJvb2xCb29sQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2Jvb2wsIGJvb2wmZ3Q7IG1hcF9ib29sX2Jvb2wgPSAxMzs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBCb29sQm9vbCgKICAgICAgICBib29sZWFuIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEJvb2xCb29sTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICBnZXRNYXBCb29sQm9vbCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICBnZXRNYXBCb29sQm9vbE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBnZXRNYXBCb29sQm9vbE9yRGVmYXVsdCgKICAgICAgICBib29sZWFuIGtleSwKICAgICAgICBib29sZWFuIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGdldE1hcEJvb2xCb29sT3JUaHJvdygKICAgICAgICBib29sZWFuIGtleSk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwU3RyaW5nU3RyaW5nQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcFN0cmluZ1N0cmluZygKICAgICAgICBqYXZhLmxhbmcuU3RyaW5nIGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFN0cmluZ1N0cmluZ01hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgIGdldE1hcFN0cmluZ1N0cmluZygpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+CiAgICBnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KamF2YS5sYW5nLlN0cmluZyBnZXRNYXBTdHJpbmdTdHJpbmdPckRlZmF1bHQoCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KamF2YS5sYW5nLlN0cmluZyBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c3RyaW5nLCBzdHJpbmcmZ3Q7IG1hcF9zdHJpbmdfc3RyaW5nID0gMTQ7PC9jb2RlPgogICAgICovCiAgICBqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yVGhyb3coCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBieXRlcyZndDsgbWFwX2ludDMyX2J5dGVzID0gMTU7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJCeXRlc0NvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgYm9vbGVhbiBjb250YWluc01hcEludDMyQnl0ZXMoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyQnl0ZXNNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICBnZXRNYXBJbnQzMkJ5dGVzKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPgogICAgZ2V0TWFwSW50MzJCeXRlc01hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGdldE1hcEludDMyQnl0ZXNPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJFbnVtQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJFbnVtKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkVudW1NYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBnZXRNYXBJbnQzMkVudW0oKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBnZXRNYXBJbnQzMkVudW1NYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlICAgICAgICAgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZUNvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJGb3JlaWduTWVzc2FnZSgKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4KICAgIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4KICAgIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CiAgfQogIC8qKgogICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0QXJlbmFNYXBMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUpCiAgICAgIFRlc3RBcmVuYU1hcExpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RBcmVuYU1hcExpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdEFyZW5hTWFwTGl0ZShjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPD8+IGJ1aWxkZXIpIHsKICAgICAgc3VwZXIoYnVpbGRlcik7CiAgICB9CiAgICBwcml2YXRlIFRlc3RBcmVuYU1hcExpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdEFyZW5hTWFwTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yOwogICAgfQoKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkUmVmbGVjdGlvbkFjY2Vzc29yIGludGVybmFsR2V0TWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgIGludCBudW1iZXIpIHsKICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCk7CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpOwogICAgICAgIGNhc2UgMzoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpOwogICAgICAgIGNhc2UgNDoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpOwogICAgICAgIGNhc2UgNToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpOwogICAgICAgIGNhc2UgNjoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpOwogICAgICAgIGNhc2UgNzoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgY2FzZSA4OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKTsKICAgICAgICBjYXNlIDk6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCk7CiAgICAgICAgY2FzZSAxMDoKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKTsKICAgICAgICBjYXNlIDExOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpOwogICAgICAgIGNhc2UgMTI6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpOwogICAgICAgIGNhc2UgMTM6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpOwogICAgICAgIGNhc2UgMTQ6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKTsKICAgICAgICBjYXNlIDE1OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpOwogICAgICAgIGNhc2UgMTY6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKTsKICAgICAgICBjYXNlIDE3OgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgfQogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuY2xhc3MsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9JTlQzMl9GSUVMRF9OVU1CRVIgPSAxOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDApOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBJbnQzMkludDMyXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKSB7CiAgICAgIGlmIChtYXBJbnQzMkludDMyXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkludDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJJbnQzMkNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkludDMyKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkludDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBJbnQzMkludDMyKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJJbnQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGludDMyJmd0OyBtYXBfaW50MzJfaW50MzIgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBJbnQzMkludDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgaW50MzImZ3Q7IG1hcF9pbnQzMl9pbnQzMiA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEludDMySW50MzJPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDY0X0lOVDY0X0ZJRUxEX05VTUJFUiA9IDI7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwSW50NjRJbnQ2NF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkgewogICAgICBpZiAobWFwSW50NjRJbnQ2NF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50NjRJbnQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDY0SW50NjRDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50NjRJbnQ2NCgKICAgICAgICBsb25nIGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDY0SW50NjRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEludDY0SW50NjQoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQ2NEludDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQ2NCwgaW50NjQmZ3Q7IG1hcF9pbnQ2NF9pbnQ2NCA9IDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcEludDY0SW50NjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEludDY0SW50NjRPckRlZmF1bHQoCiAgICAgICAgbG9uZyBrZXksCiAgICAgICAgbG9uZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDY0LCBpbnQ2NCZndDsgbWFwX2ludDY0X2ludDY0ID0gMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEludDY0SW50NjRPclRocm93KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9VSU5UMzJfVUlOVDMyX0ZJRUxEX05VTUJFUiA9IDM7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuVUlOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlVJTlQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFVpbnQzMlVpbnQzMl87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKSB7CiAgICAgIGlmIChtYXBVaW50MzJVaW50MzJfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwVWludDMyVWludDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFVpbnQzMlVpbnQzMigKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBVaW50MzJVaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFVpbnQzMlVpbnQzMigpIHsKICAgICAgcmV0dXJuIGdldE1hcFVpbnQzMlVpbnQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwVWludDMyVWludDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3VpbnQzMiwgdWludDMyJmd0OyBtYXBfdWludDMyX3VpbnQzMiA9IDM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQzMlVpbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDMyLCB1aW50MzImZ3Q7IG1hcF91aW50MzJfdWludDMyID0gMzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwVWludDMyVWludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX1VJTlQ2NF9VSU5UNjRfRklFTERfTlVNQkVSID0gNDsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcFVpbnQ2NFVpbnQ2NERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBVaW50NjRVaW50NjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5VSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlVJTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBVaW50NjRVaW50NjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkgewogICAgICBpZiAobWFwVWludDY0VWludDY0XyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFVpbnQ2NFVpbnQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFVpbnQ2NFVpbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBVaW50NjRVaW50NjQoCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFVpbnQ2NFVpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwVWludDY0VWludDY0KCkgewogICAgICByZXR1cm4gZ2V0TWFwVWludDY0VWludDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBVaW50NjRVaW50NjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7dWludDY0LCB1aW50NjQmZ3Q7IG1hcF91aW50NjRfdWludDY0ID0gNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcFVpbnQ2NFVpbnQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDt1aW50NjQsIHVpbnQ2NCZndDsgbWFwX3VpbnQ2NF91aW50NjQgPSA0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwVWludDY0VWludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TSU5UMzJfU0lOVDMyX0ZJRUxEX05VTUJFUiA9IDU7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0lOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNJTlQzMiwKICAgICAgICAgICAgICAgICAgMCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcFNpbnQzMlNpbnQzMl87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSB7CiAgICAgIGlmIChtYXBTaW50MzJTaW50MzJfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgfQogICAgICByZXR1cm4gbWFwU2ludDMyU2ludDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcFNpbnQzMlNpbnQzMigKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTaW50MzJTaW50MzJNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcFNpbnQzMlNpbnQzMigpIHsKICAgICAgcmV0dXJuIGdldE1hcFNpbnQzMlNpbnQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwU2ludDMyU2ludDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NpbnQzMiwgc2ludDMyJmd0OyBtYXBfc2ludDMyX3NpbnQzMiA9IDU7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQzMlNpbnQzMk9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIGludCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDMyLCBzaW50MzImZ3Q7IG1hcF9zaW50MzJfc2ludDMyID0gNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ludDMyU2ludDMyT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX1NJTlQ2NF9TSU5UNjRfRklFTERfTlVNQkVSID0gNjsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcFNpbnQ2NFNpbnQ2NERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50NjRTaW50NjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TSU5UNjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNJTlQ2NCwKICAgICAgICAgICAgICAgICAgMEwpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXBTaW50NjRTaW50NjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkgewogICAgICBpZiAobWFwU2ludDY0U2ludDY0XyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU2ludDY0U2ludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFNpbnQ2NFNpbnQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFNpbnQ2NFNpbnQ2NENvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTaW50NjRTaW50NjQoCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcFNpbnQ2NFNpbnQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ludDY0U2ludDY0KCkgewogICAgICByZXR1cm4gZ2V0TWFwU2ludDY0U2ludDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBTaW50NjRTaW50NjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ludDY0LCBzaW50NjQmZ3Q7IG1hcF9zaW50NjRfc2ludDY0ID0gNjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcFNpbnQ2NFNpbnQ2NE9yRGVmYXVsdCgKICAgICAgICBsb25nIGtleSwKICAgICAgICBsb25nIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzaW50NjQsIHNpbnQ2NCZndDsgbWFwX3NpbnQ2NF9zaW50NjQgPSA2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwU2ludDY0U2ludDY0T3JUaHJvdygKICAgICAgICBsb25nIGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9GSVhFRDMyX0ZJWEVEMzJfRklFTERfTlVNQkVSID0gNzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEZpeGVkMzJGaXhlZDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRklYRUQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDMyLAogICAgICAgICAgICAgICAgICAwKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwRml4ZWQzMkZpeGVkMzJfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgIGlmIChtYXBGaXhlZDMyRml4ZWQzMl8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEZpeGVkMzJGaXhlZDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwRml4ZWQzMkZpeGVkMzJDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDMyLCBmaXhlZDMyJmd0OyBtYXBfZml4ZWQzMl9maXhlZDMyID0gNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwRml4ZWQzMkZpeGVkMzIoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZ2V0TWFwRml4ZWQzMkZpeGVkMzIoKSB7CiAgICAgIHJldHVybiBnZXRNYXBGaXhlZDMyRml4ZWQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGdldE1hcEZpeGVkMzJGaXhlZDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQzMiwgZml4ZWQzMiZndDsgbWFwX2ZpeGVkMzJfZml4ZWQzMiA9IDc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkMzJGaXhlZDMyT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgaW50IGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcC5nZXQoa2V5KSA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ZpeGVkMzIsIGZpeGVkMzImZ3Q7IG1hcF9maXhlZDMyX2ZpeGVkMzIgPSA3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRNYXBGaXhlZDMyRml4ZWQzMk9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0ZJWEVENjRfRklYRUQ2NF9GSUVMRF9OVU1CRVIgPSA4OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwRml4ZWQ2NEZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcEZpeGVkNjRGaXhlZDY0XzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkgewogICAgICBpZiAobWFwRml4ZWQ2NEZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBGaXhlZDY0Rml4ZWQ2NF87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEZpeGVkNjRGaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEZpeGVkNjRGaXhlZDY0KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBnZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEZpeGVkNjRGaXhlZDY0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwRml4ZWQ2NEZpeGVkNjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtmaXhlZDY0LCBmaXhlZDY0Jmd0OyBtYXBfZml4ZWQ2NF9maXhlZDY0ID0gODs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBsb25nIGdldE1hcEZpeGVkNjRGaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Zml4ZWQ2NCwgZml4ZWQ2NCZndDsgbWFwX2ZpeGVkNjRfZml4ZWQ2NCA9IDg7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBGaXhlZDY0Rml4ZWQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TRklYRUQzMl9TRklYRUQzMl9GSUVMRF9OVU1CRVIgPSA5OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0ZJWEVEMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0ZJWEVEMzIsCiAgICAgICAgICAgICAgICAgIDApOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBTZml4ZWQzMlNmaXhlZDMyXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKSB7CiAgICAgIGlmIChtYXBTZml4ZWQzMlNmaXhlZDMyXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU2ZpeGVkMzJTZml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBTZml4ZWQzMlNmaXhlZDMyXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMkNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQzMlNmaXhlZDMyKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkgewogICAgICByZXR1cm4gZ2V0TWFwU2ZpeGVkMzJTZml4ZWQzMk1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7c2ZpeGVkMzIsIHNmaXhlZDMyJmd0OyBtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIgPSA5OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBnZXRNYXBTZml4ZWQzMlNmaXhlZDMyTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBpbnQgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQzMiwgc2ZpeGVkMzImZ3Q7IG1hcF9zZml4ZWQzMl9zZml4ZWQzMiA9IDk7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldE1hcFNmaXhlZDMyU2ZpeGVkMzJPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX1NGSVhFRDY0X1NGSVhFRDY0X0ZJRUxEX05VTUJFUiA9IDEwOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU2ZpeGVkNjRTZml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU0ZJWEVENjQsCiAgICAgICAgICAgICAgICAgIDBMLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLlNGSVhFRDY0LAogICAgICAgICAgICAgICAgICAwTCk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgaWYgKG1hcFNmaXhlZDY0U2ZpeGVkNjRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFNmaXhlZDY0U2ZpeGVkNjRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBTZml4ZWQ2NFNmaXhlZDY0KAogICAgICAgIGxvbmcga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpIHsKICAgICAgcmV0dXJuIGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGdldE1hcFNmaXhlZDY0U2ZpeGVkNjRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3NmaXhlZDY0LCBzZml4ZWQ2NCZndDsgbWFwX3NmaXhlZDY0X3NmaXhlZDY0ID0gMTA7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgbG9uZyBnZXRNYXBTZml4ZWQ2NFNmaXhlZDY0T3JEZWZhdWx0KAogICAgICAgIGxvbmcga2V5LAogICAgICAgIGxvbmcgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzZml4ZWQ2NCwgc2ZpeGVkNjQmZ3Q7IG1hcF9zZml4ZWQ2NF9zZml4ZWQ2NCA9IDEwOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGxvbmcgZ2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NE9yVGhyb3coCiAgICAgICAgbG9uZyBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0ZMT0FUX0ZJRUxEX05VTUJFUiA9IDExOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0Pm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5GTE9BVCwKICAgICAgICAgICAgICAgICAgMEYpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwSW50MzJGbG9hdF87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4KICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpIHsKICAgICAgaWYgKG1hcEludDMyRmxvYXRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkZsb2F0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRmxvYXRfOwogICAgfQogICAgcHVibGljIGludCBnZXRNYXBJbnQzMkZsb2F0Q291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZsb2F0KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZsb2F0TWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZ2V0TWFwSW50MzJGbG9hdCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEludDMyRmxvYXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBmbG9hdCZndDsgbWFwX2ludDMyX2Zsb2F0ID0gMTE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PiBnZXRNYXBJbnQzMkZsb2F0TWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZsb2F0IGdldE1hcEludDMyRmxvYXRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBmbG9hdCBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZmxvYXQmZ3Q7IG1hcF9pbnQzMl9mbG9hdCA9IDExOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZsb2F0IGdldE1hcEludDMyRmxvYXRPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9ET1VCTEVfRklFTERfTlVNQkVSID0gMTI7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJEb3VibGVFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5ET1VCTEUsCiAgICAgICAgICAgICAgICAgIDBEKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXBJbnQzMkRvdWJsZV87CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkgewogICAgICBpZiAobWFwSW50MzJEb3VibGVfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkRvdWJsZV87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDMyRG91YmxlQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGRvdWJsZSZndDsgbWFwX2ludDMyX2RvdWJsZSA9IDEyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkRvdWJsZSgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRG91YmxlTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+IGdldE1hcEludDMyRG91YmxlKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJEb3VibGVNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBnZXRNYXBJbnQzMkRvdWJsZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCBkb3VibGUmZ3Q7IG1hcF9pbnQzMl9kb3VibGUgPSAxMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBkb3VibGUgZ2V0TWFwSW50MzJEb3VibGVPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICBkb3VibGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgZG91YmxlJmd0OyBtYXBfaW50MzJfZG91YmxlID0gMTI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZG91YmxlIGdldE1hcEludDMyRG91YmxlT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9CT09MX0JPT0xfRklFTERfTlVNQkVSID0gMTM7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkJPT0wsCiAgICAgICAgICAgICAgICAgIGZhbHNlLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLkJPT0wsCiAgICAgICAgICAgICAgICAgIGZhbHNlKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4gbWFwQm9vbEJvb2xfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5Cb29sZWFuLCBqYXZhLmxhbmcuQm9vbGVhbj4KICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKSB7CiAgICAgIGlmIChtYXBCb29sQm9vbF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEJvb2xCb29sXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwQm9vbEJvb2xDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEJvb2xCb29sKAogICAgICAgIGJvb2xlYW4ga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEJvb2xCb29sTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBnZXRNYXBCb29sQm9vbCgpIHsKICAgICAgcmV0dXJuIGdldE1hcEJvb2xCb29sTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGdldE1hcEJvb2xCb29sTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7Ym9vbCwgYm9vbCZndDsgbWFwX2Jvb2xfYm9vbCA9IDEzOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZ2V0TWFwQm9vbEJvb2xPckRlZmF1bHQoCiAgICAgICAgYm9vbGVhbiBrZXksCiAgICAgICAgYm9vbGVhbiBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtib29sLCBib29sJmd0OyBtYXBfYm9vbF9ib29sID0gMTM7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBnZXRNYXBCb29sQm9vbE9yVGhyb3coCiAgICAgICAgYm9vbGVhbiBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9TVFJJTkdfU1RSSU5HX0ZJRUxEX05VTUJFUiA9IDE0OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuU1RSSU5HLAogICAgICAgICAgICAgICAgICAiIiwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5TVFJJTkcsCiAgICAgICAgICAgICAgICAgICIiKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcFN0cmluZ1N0cmluZ187CiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkgewogICAgICBpZiAobWFwU3RyaW5nU3RyaW5nXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcFN0cmluZ1N0cmluZ187CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcFN0cmluZ1N0cmluZ0NvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwU3RyaW5nU3RyaW5nKAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5KSB7CiAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBnZXRNYXBTdHJpbmdTdHJpbmcoKSB7CiAgICAgIHJldHVybiBnZXRNYXBTdHJpbmdTdHJpbmdNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gZ2V0TWFwU3RyaW5nU3RyaW5nTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O3N0cmluZywgc3RyaW5nJmd0OyBtYXBfc3RyaW5nX3N0cmluZyA9IDE0OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZ2V0TWFwU3RyaW5nU3RyaW5nT3JEZWZhdWx0KAogICAgICAgIGphdmEubGFuZy5TdHJpbmcga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmphdmEubGFuZy5TdHJpbmcgZGVmYXVsdFZhbHVlKSB7CiAgICAgIGlmIChrZXkgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCBrZXkiKTsgfQogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5TdHJpbmcsIGphdmEubGFuZy5TdHJpbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtzdHJpbmcsIHN0cmluZyZndDsgbWFwX3N0cmluZ19zdHJpbmcgPSAxNDs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLmxhbmcuU3RyaW5nIGdldE1hcFN0cmluZ1N0cmluZ09yVGhyb3coCiAgICAgICAgamF2YS5sYW5nLlN0cmluZyBrZXkpIHsKICAgICAgaWYgKGtleSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIGtleSIpOyB9CiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkuZ2V0TWFwKCk7CiAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICB9CiAgICAgIHJldHVybiBtYXAuZ2V0KGtleSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0JZVEVTX0ZJRUxEX05VTUJFUiA9IDE1OwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5CWVRFUywKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nLkVNUFRZKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG1hcEludDMyQnl0ZXNfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKSB7CiAgICAgIGlmIChtYXBJbnQzMkJ5dGVzXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJCeXRlc0RlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkJ5dGVzXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJCeXRlc0NvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJCeXRlcygKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJCeXRlc01hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IGdldE1hcEludDMyQnl0ZXMoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQzMkJ5dGVzTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gZ2V0TWFwSW50MzJCeXRlc01hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIGJ5dGVzJmd0OyBtYXBfaW50MzJfYnl0ZXMgPSAxNTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZ2V0TWFwSW50MzJCeXRlc09yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgYnl0ZXMmZ3Q7IG1hcF9pbnQzMl9ieXRlcyA9IDE1OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBnZXRNYXBJbnQzMkJ5dGVzT3JUaHJvdygKICAgICAgICBpbnQga2V5KSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcC5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfSU5UMzJfRU5VTV9GSUVMRF9OVU1CRVIgPSAxNjsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyRW51bURlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkVudW1FbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5FTlVNLAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUuTUFQX0VOVU1fRk9PX0xJVEUuZ2V0TnVtYmVyKCkpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXBJbnQzMkVudW1fOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkgewogICAgICBpZiAobWFwSW50MzJFbnVtXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJFbnVtRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyRW51bV87CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPiBtYXBJbnQzMkVudW1WYWx1ZUNvbnZlcnRlciA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5uZXdFbnVtQ29udmVydGVyKAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlLmludGVybmFsR2V0VmFsdWVNYXAoKSwKICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZS5NQVBfRU5VTV9GT09fTElURSk7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICBpbnRlcm5hbEdldEFkYXB0ZWRNYXBJbnQzMkVudW1NYXAoCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCkgewogICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlcjwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUsIGphdmEubGFuZy5JbnRlZ2VyPigKICAgICAgICAgICAgICBtYXAsIG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyKTsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJFbnVtQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRW51bSgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkVudW1NYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgZ2V0TWFwSW50MzJFbnVtKCkgewogICAgICByZXR1cm4gZ2V0TWFwSW50MzJFbnVtTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZT4KICAgIGdldE1hcEludDMyRW51bU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCkpO30KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGdldE1hcEludDMyRW51bU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpCiAgICAgICAgICAgICA/IG1hcEludDMyRW51bVZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlIGdldE1hcEludDMyRW51bU9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgTUFQX0lOVDMyX0ZPUkVJR05fTUVTU0FHRV9GSUVMRF9OVU1CRVIgPSAxNzsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuTUVTU0FHRSwKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+CiAgICBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgIGlmIChtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJGb3JlaWduTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZUNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgcmV0dXJuIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCksCiAgICAgICAgICBNYXBJbnQzMkludDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKSwKICAgICAgICAgIE1hcEludDY0SW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMik7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCksCiAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMyk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUxvbmdNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwVWludDY0VWludDY0KCksCiAgICAgICAgICBNYXBVaW50NjRVaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgNCk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCksCiAgICAgICAgICBNYXBTaW50MzJTaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgNSk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUxvbmdNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCksCiAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgNik7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSwKICAgICAgICAgIE1hcEZpeGVkMzJGaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDcpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCksCiAgICAgICAgICBNYXBGaXhlZDY0Rml4ZWQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICA4KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCksCiAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDkpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVMb25nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKSwKICAgICAgICAgIE1hcFNmaXhlZDY0U2ZpeGVkNjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTApOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKSwKICAgICAgICAgIE1hcEludDMyRmxvYXREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTEpOwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCksCiAgICAgICAgICBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxMik7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUJvb2xlYW5NYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwQm9vbEJvb2woKSwKICAgICAgICAgIE1hcEJvb2xCb29sRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEzKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplU3RyaW5nTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLAogICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDE0KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCksCiAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDE1KTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKSwKICAgICAgICAgIE1hcEludDMyRW51bURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxNik7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLAogICAgICAgICAgTWFwSW50MzJGb3JlaWduTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxNyk7CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcEludDMySW50MzJfXyA9IE1hcEludDMySW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEsIG1hcEludDMySW50MzJfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBJbnQ2NEludDY0X18gPSBNYXBJbnQ2NEludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgyLCBtYXBJbnQ2NEludDY0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBtYXBVaW50MzJVaW50MzJfXyA9IE1hcFVpbnQzMlVpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMywgbWFwVWludDMyVWludDMyX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBVaW50NjRVaW50NjRfXyA9IE1hcFVpbnQ2NFVpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNCwgbWFwVWludDY0VWludDY0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFNpbnQzMlNpbnQzMigpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBtYXBTaW50MzJTaW50MzJfXyA9IE1hcFNpbnQzMlNpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNSwgbWFwU2ludDMyU2ludDMyX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBTaW50NjRTaW50NjRfXyA9IE1hcFNpbnQ2NFNpbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNiwgbWFwU2ludDY0U2ludDY0X18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcEZpeGVkMzJGaXhlZDMyX18gPSBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoNywgbWFwRml4ZWQzMkZpeGVkMzJfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgbWFwRml4ZWQ2NEZpeGVkNjRfXyA9IE1hcEZpeGVkNjRGaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSg4LCBtYXBGaXhlZDY0Rml4ZWQ2NF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIG1hcFNmaXhlZDMyU2ZpeGVkMzJfXyA9IE1hcFNmaXhlZDMyU2ZpeGVkMzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDksIG1hcFNmaXhlZDMyU2ZpeGVkMzJfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICBtYXBTZml4ZWQ2NFNmaXhlZDY0X18gPSBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMCwgbWFwU2ZpeGVkNjRTZml4ZWQ2NF9fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5GbG9hdD4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRmxvYXQ+CiAgICAgICAgbWFwSW50MzJGbG9hdF9fID0gTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTEsIG1hcEludDMyRmxvYXRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuRG91YmxlPgogICAgICAgIG1hcEludDMyRG91YmxlX18gPSBNYXBJbnQzMkRvdWJsZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTIsIG1hcEludDMyRG91YmxlX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkJvb2xlYW4sIGphdmEubGFuZy5Cb29sZWFuPgogICAgICAgIG1hcEJvb2xCb29sX18gPSBNYXBCb29sQm9vbERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTMsIG1hcEJvb2xCb29sX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuU3RyaW5nLCBqYXZhLmxhbmcuU3RyaW5nPgogICAgICAgIG1hcFN0cmluZ1N0cmluZ19fID0gTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxNCwgbWFwU3RyaW5nU3RyaW5nX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZz4KICAgICAgICBtYXBJbnQzMkJ5dGVzX18gPSBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxNSwgbWFwSW50MzJCeXRlc19fKTsKICAgICAgfQogICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBlbnRyeQogICAgICAgICAgIDogaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgbWFwSW50MzJFbnVtX18gPSBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE2LCBtYXBJbnQzMkVudW1fXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPgogICAgICAgIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfXyA9IE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDE3LCBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlX18pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBvdGhlciA9IChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkgb2JqOwoKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMySW50MzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDY0SW50NjQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFVpbnQzMlVpbnQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFNpbnQ2NFNpbnQ2NCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwQm9vbEJvb2woKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFpbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRW51bSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0lOVDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMySW50MzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDY0X0lOVDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfVUlOVDMyX1VJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfVUlOVDY0X1VJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfU0lOVDMyX1NJTlQzMl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfU0lOVDY0X1NJTlQ2NF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9GSVhFRDMyX0ZJWEVEMzJfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwRml4ZWQzMkZpeGVkMzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaXhlZDY0Rml4ZWQ2NCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9GSVhFRDY0X0ZJWEVENjRfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTZml4ZWQzMlNmaXhlZDMyKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1NGSVhFRDMyX1NGSVhFRDMyX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX1NGSVhFRDY0X1NGSVhFRDY0X0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkZsb2F0KCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0ZMT0FUX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkRvdWJsZSgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9JTlQzMl9ET1VCTEVfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwSW50MzJEb3VibGUoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIE1BUF9CT09MX0JPT0xfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwQm9vbEJvb2woKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfU1RSSU5HX1NUUklOR19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0JZVEVTX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldE1hcEludDMyQnl0ZXMoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UMzJfRU5VTV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgTUFQX0lOVDMyX0ZPUkVJR05fTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICAgIGludCBudW1iZXIpIHsKICAgICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkludDMyKCk7CiAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDY0SW50NjQoKTsKICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwVWludDMyVWludDMyKCk7CiAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFVpbnQ2NFVpbnQ2NCgpOwogICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKTsKICAgICAgICAgIGNhc2UgNjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCk7CiAgICAgICAgICBjYXNlIDc6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAgICAgICBjYXNlIDk6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDMyU2ZpeGVkMzIoKTsKICAgICAgICAgIGNhc2UgMTA6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcFNmaXhlZDY0U2ZpeGVkNjQoKTsKICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKTsKICAgICAgICAgIGNhc2UgMTI6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCk7CiAgICAgICAgICBjYXNlIDEzOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpOwogICAgICAgICAgY2FzZSAxNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwU3RyaW5nU3RyaW5nKCk7CiAgICAgICAgICBjYXNlIDE1OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCk7CiAgICAgICAgICBjYXNlIDE2OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKTsKICAgICAgICAgIGNhc2UgMTc6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCk7CiAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCk7CiAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKTsKICAgICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpOwogICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDMyU2ludDMyKCk7CiAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKTsKICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDY0Rml4ZWQ2NCgpOwogICAgICAgICAgY2FzZSA5OgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgICAgICAgY2FzZSAxMDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKTsKICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCk7CiAgICAgICAgICBjYXNlIDEyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKTsKICAgICAgICAgIGNhc2UgMTM6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpOwogICAgICAgICAgY2FzZSAxNDoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpOwogICAgICAgICAgY2FzZSAxNToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKTsKICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKTsKICAgICAgICAgIGNhc2UgMTc6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuY2xhc3MsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDY0SW50NjQoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQzMlVpbnQzMigpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDY0VWludDY0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNpbnQ2NFNpbnQ2NCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQzMkZpeGVkMzIoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQzMlNmaXhlZDMyKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTZml4ZWQ2NFNmaXhlZDY0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkRvdWJsZSgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuY2xlYXIoKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBidWlsZCgpIHsKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSByZXN1bHQgPSBuZXcgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkludDMyXyA9IGludGVybmFsR2V0TWFwSW50MzJJbnQzMigpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMySW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQ2NEludDY0XyA9IGludGVybmFsR2V0TWFwSW50NjRJbnQ2NCgpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDY0SW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50MzJVaW50MzJfID0gaW50ZXJuYWxHZXRNYXBVaW50MzJVaW50MzIoKTsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50MzJVaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwOCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50NjRVaW50NjRfID0gaW50ZXJuYWxHZXRNYXBVaW50NjRVaW50NjQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBVaW50NjRVaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAxMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50MzJTaW50MzJfID0gaW50ZXJuYWxHZXRNYXBTaW50MzJTaW50MzIoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50MzJTaW50MzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAyMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50NjRTaW50NjRfID0gaW50ZXJuYWxHZXRNYXBTaW50NjRTaW50NjQoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTaW50NjRTaW50NjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA0MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBGaXhlZDMyRml4ZWQzMl8gPSBpbnRlcm5hbEdldE1hcEZpeGVkMzJGaXhlZDMyKCk7CiAgICAgICAgICByZXN1bHQubWFwRml4ZWQzMkZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDA4MCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBGaXhlZDY0Rml4ZWQ2NF8gPSBpbnRlcm5hbEdldE1hcEZpeGVkNjRGaXhlZDY0KCk7CiAgICAgICAgICByZXN1bHQubWFwRml4ZWQ2NEZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDEwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTZml4ZWQzMlNmaXhlZDMyXyA9IGludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpOwogICAgICAgICAgcmVzdWx0Lm1hcFNmaXhlZDMyU2ZpeGVkMzJfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDIwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTZml4ZWQ2NFNmaXhlZDY0XyA9IGludGVybmFsR2V0TWFwU2ZpeGVkNjRTZml4ZWQ2NCgpOwogICAgICAgICAgcmVzdWx0Lm1hcFNmaXhlZDY0U2ZpeGVkNjRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDQwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkZsb2F0XyA9IGludGVybmFsR2V0TWFwSW50MzJGbG9hdCgpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMyRmxvYXRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDgwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkRvdWJsZV8gPSBpbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCk7CiAgICAgICAgICByZXN1bHQubWFwSW50MzJEb3VibGVfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMTAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBCb29sQm9vbF8gPSBpbnRlcm5hbEdldE1hcEJvb2xCb29sKCk7CiAgICAgICAgICByZXN1bHQubWFwQm9vbEJvb2xfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMjAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBTdHJpbmdTdHJpbmdfID0gaW50ZXJuYWxHZXRNYXBTdHJpbmdTdHJpbmcoKTsKICAgICAgICAgIHJlc3VsdC5tYXBTdHJpbmdTdHJpbmdfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwNDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkJ5dGVzXyA9IGludGVybmFsR2V0TWFwSW50MzJCeXRlcygpOwogICAgICAgICAgcmVzdWx0Lm1hcEludDMyQnl0ZXNfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwODAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkVudW1fID0gaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKTsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkVudW1fLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAxMDAwMCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5tYXBJbnQzMkZvcmVpZ25NZXNzYWdlXyA9IGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmJ1aWxkKE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20ocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMySW50MzIoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJJbnQzMigpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50NjRJbnQ2NCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQ2NEludDY0KCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50MzJVaW50MzIoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwVWludDMyVWludDMyKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwNDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBVaW50NjRVaW50NjQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwVWludDY0VWludDY0KCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwODsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ludDMyU2ludDMyKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50NjRTaW50NjQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ludDY0U2ludDY0KCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAyMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBGaXhlZDMyRml4ZWQzMigpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwNDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRml4ZWQ2NEZpeGVkNjQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwRml4ZWQ2NEZpeGVkNjQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwU2ZpeGVkMzJTZml4ZWQzMigpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAxMDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ZpeGVkNjRTZml4ZWQ2NCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBTZml4ZWQ2NFNmaXhlZDY0KCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDIwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRmxvYXQoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwNDAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRG91YmxlKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRG91YmxlKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDgwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBCb29sQm9vbCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBCb29sQm9vbCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU3RyaW5nU3RyaW5nKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcFN0cmluZ1N0cmluZygpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDIwMDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJCeXRlcygpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRNYXBJbnQzMkJ5dGVzKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwNDAwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJFbnVtKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDEwMDAwOwogICAgICAgIHRoaXMubWVyZ2VVbmtub3duRmllbGRzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSk7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgICBpZiAoZXh0ZW5zaW9uUmVnaXN0cnkgPT0gbnVsbCkgewogICAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgYm9vbGVhbiBkb25lID0gZmFsc2U7CiAgICAgICAgICB3aGlsZSAoIWRvbmUpIHsKICAgICAgICAgICAgaW50IHRhZyA9IGlucHV0LnJlYWRUYWcoKTsKICAgICAgICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgMTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwSW50MzJJbnQzMl9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJJbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkludDMyKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkludDMyX18uZ2V0S2V5KCksIG1hcEludDMySW50MzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxMAogICAgICAgICAgICAgIGNhc2UgMTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwSW50NjRJbnQ2NF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50NjRJbnQ2NERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQ2NEludDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQ2NEludDY0X18uZ2V0S2V5KCksIG1hcEludDY0SW50NjRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSAxOAogICAgICAgICAgICAgIGNhc2UgMjY6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwVWludDMyVWludDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBVaW50MzJVaW50MzJEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwVWludDMyVWludDMyKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBVaW50MzJVaW50MzJfXy5nZXRLZXkoKSwgbWFwVWludDMyVWludDMyX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMjYKICAgICAgICAgICAgICBjYXNlIDM0OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5Mb25nLCBqYXZhLmxhbmcuTG9uZz4KICAgICAgICAgICAgICAgIG1hcFVpbnQ2NFVpbnQ2NF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwVWludDY0VWludDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFVpbnQ2NFVpbnQ2NCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwVWludDY0VWludDY0X18uZ2V0S2V5KCksIG1hcFVpbnQ2NFVpbnQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA4OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDM0CiAgICAgICAgICAgICAgY2FzZSA0MjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBtYXBTaW50MzJTaW50MzJfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcFNpbnQzMlNpbnQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBTaW50MzJTaW50MzIoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNpbnQzMlNpbnQzMl9fLmdldEtleSgpLCBtYXBTaW50MzJTaW50MzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAxMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA0MgogICAgICAgICAgICAgIGNhc2UgNTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwU2ludDY0U2ludDY0X18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTaW50NjRTaW50NjREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwU2ludDY0U2ludDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBTaW50NjRTaW50NjRfXy5nZXRLZXkoKSwgbWFwU2ludDY0U2ludDY0X18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMjA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgNTAKICAgICAgICAgICAgICBjYXNlIDU4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIG1hcEZpeGVkMzJGaXhlZDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBGaXhlZDMyRml4ZWQzMkRlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaXhlZDMyRml4ZWQzMigpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwRml4ZWQzMkZpeGVkMzJfXy5nZXRLZXkoKSwgbWFwRml4ZWQzMkZpeGVkMzJfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDA0MDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA1OAogICAgICAgICAgICAgIGNhc2UgNjY6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkxvbmcsIGphdmEubGFuZy5Mb25nPgogICAgICAgICAgICAgICAgbWFwRml4ZWQ2NEZpeGVkNjRfXyA9IGlucHV0LnJlYWRNZXNzYWdlKAogICAgICAgICAgICAgICAgICAgIE1hcEZpeGVkNjRGaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpeGVkNjRGaXhlZDY0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBGaXhlZDY0Rml4ZWQ2NF9fLmdldEtleSgpLCBtYXBGaXhlZDY0Rml4ZWQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDgwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDY2CiAgICAgICAgICAgICAgY2FzZSA3NDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBtYXBTZml4ZWQzMlNmaXhlZDMyX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTZml4ZWQzMlNmaXhlZDMyRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDMyU2ZpeGVkMzIoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNmaXhlZDMyU2ZpeGVkMzJfXy5nZXRLZXkoKSwgbWFwU2ZpeGVkMzJTZml4ZWQzMl9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMTAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDc0CiAgICAgICAgICAgICAgY2FzZSA4MjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuTG9uZywgamF2YS5sYW5nLkxvbmc+CiAgICAgICAgICAgICAgICBtYXBTZml4ZWQ2NFNmaXhlZDY0X18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBTZml4ZWQ2NFNmaXhlZDY0RGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFNmaXhlZDY0U2ZpeGVkNjQoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcFNmaXhlZDY0U2ZpeGVkNjRfXy5nZXRLZXkoKSwgbWFwU2ZpeGVkNjRTZml4ZWQ2NF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMjAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgyCiAgICAgICAgICAgICAgY2FzZSA5MDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkZsb2F0PgogICAgICAgICAgICAgICAgbWFwSW50MzJGbG9hdF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJGbG9hdERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZsb2F0KCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMkZsb2F0X18uZ2V0S2V5KCksIG1hcEludDMyRmxvYXRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDQwMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA5MAogICAgICAgICAgICAgIGNhc2UgOTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5Eb3VibGU+CiAgICAgICAgICAgICAgICBtYXBJbnQzMkRvdWJsZV9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwSW50MzJEb3VibGVEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJEb3VibGUoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEludDMyRG91YmxlX18uZ2V0S2V5KCksIG1hcEludDMyRG91YmxlX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDA4MDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOTgKICAgICAgICAgICAgICBjYXNlIDEwNjogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuQm9vbGVhbiwgamF2YS5sYW5nLkJvb2xlYW4+CiAgICAgICAgICAgICAgICBtYXBCb29sQm9vbF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwQm9vbEJvb2xEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwQm9vbEJvb2woKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEJvb2xCb29sX18uZ2V0S2V5KCksIG1hcEJvb2xCb29sX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDEwMDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTA2CiAgICAgICAgICAgICAgY2FzZSAxMTQ6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLlN0cmluZywgamF2YS5sYW5nLlN0cmluZz4KICAgICAgICAgICAgICAgIG1hcFN0cmluZ1N0cmluZ19fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwU3RyaW5nU3RyaW5nRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcFN0cmluZ1N0cmluZygpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgbWFwU3RyaW5nU3RyaW5nX18uZ2V0S2V5KCksIG1hcFN0cmluZ1N0cmluZ19fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAyMDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDExNAogICAgICAgICAgICAgIGNhc2UgMTIyOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmc+CiAgICAgICAgICAgICAgICBtYXBJbnQzMkJ5dGVzX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBJbnQzMkJ5dGVzRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCksIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyQnl0ZXMoKS5nZXRNdXRhYmxlTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEludDMyQnl0ZXNfXy5nZXRLZXkoKSwgbWFwSW50MzJCeXRlc19fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA0MDAwOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEyMgogICAgICAgICAgICAgIGNhc2UgMTMwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnl0ZXMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgbWFwSW50MzJFbnVtX18gPSBNYXBJbnQzMkVudW1EZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKS5wYXJzZUZyb20oYnl0ZXMpOwogICAgICAgICAgICAgICAgaWYgKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZS5mb3JOdW1iZXIobWFwSW50MzJFbnVtX18uZ2V0VmFsdWUoKSkgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25MZW5ndGhEZWxpbWl0ZWRGaWVsZCgxNiwgYnl0ZXMpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICAgIG1hcEludDMyRW51bV9fLmdldEtleSgpLCBtYXBJbnQzMkVudW1fXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDEzMAogICAgICAgICAgICAgIGNhc2UgMTM4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+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+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyRW51bSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwSW50MzJFbnVtTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0Lk1hcEVudW1MaXRlPgogICAgICBnZXRNYXBJbnQzMkVudW0oKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEludDMyRW51bU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICAgIGdldE1hcEludDMyRW51bU1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkTWFwSW50MzJFbnVtTWFwKAogICAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyRW51bSgpLmdldE1hcCgpKTt9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGUgZ2V0TWFwSW50MzJFbnVtT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0TWFwSW50MzJFbnVtKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpCiAgICAgICAgICAgICAgID8gbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSkKICAgICAgICAgICAgICAgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0Lk1hcEVudW1MaXRlJmd0OyBtYXBfaW50MzJfZW51bSA9IDE2OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSBnZXRNYXBJbnQzMkVudW1PclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkVudW0oKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJFbnVtVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQzMkVudW0oKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDgwMDApOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyRW51bSgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJFbnVtKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkVudW0oKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkTWFwSW50MzJFbnVtTWFwKAogICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuTWFwRW51bUxpdGUmZ3Q7IG1hcF9pbnQzMl9lbnVtID0gMTY7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJFbnVtKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5NYXBFbnVtTGl0ZSB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5wdXQoa2V5LCBtYXBJbnQzMkVudW1WYWx1ZUNvbnZlcnRlci5kb0JhY2t3YXJkKHZhbHVlKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDA4MDAwOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtTGl0ZSZndDsgbWFwX2ludDMyX2VudW0gPSAxNjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQzMkVudW0oCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuTWFwRW51bUxpdGU+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0QWRhcHRlZE1hcEludDMyRW51bU1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJFbnVtKCkuZ2V0TXV0YWJsZU1hcCgpKQogICAgICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwODAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlciBpbXBsZW1lbnRzIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyLkNvbnZlcnRlcjxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlT3JCdWlsZGVyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IHsKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBidWlsZChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXIgdmFsKSB7CiAgICAgICAgICBpZiAodmFsIGluc3RhbmNlb2YgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKSB7IHJldHVybiAocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKSB2YWw7IH0KICAgICAgICAgIHJldHVybiAoKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZS5CdWlsZGVyKSB2YWwpLmJ1aWxkKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gZGVmYXVsdEVudHJ5KCkgewogICAgICAgICAgcmV0dXJuIE1hcEludDMyRm9yZWlnbk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5OwogICAgICAgIH0KICAgICAgfTsKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgTWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlciBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlQ29udmVydGVyID0gbmV3IE1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIoKTsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlT3JCdWlsZGVyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZS5CdWlsZGVyPiBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlT3JCdWlsZGVyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZS5CdWlsZGVyPgogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGlmIChtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPD4obWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlcik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLkJ1aWxkZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGlmIChtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXyA9PSBudWxsKSB7CiAgICAgICAgICBtYXBJbnQzMkZvcmVpZ25NZXNzYWdlXyA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjw+KG1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMTAwMDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDMyRm9yZWlnbk1lc3NhZ2VfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZUNvdW50KCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2UoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGU+IGdldE1hcEludDMyRm9yZWlnbk1lc3NhZ2VNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmdldEltbXV0YWJsZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSZndDsgbWFwX2ludDMyX2ZvcmVpZ25fbWVzc2FnZSA9IDE3OzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBnZXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlT3JCdWlsZGVyPiBtYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KSA/IG1hcEludDMyRm9yZWlnbk1lc3NhZ2VDb252ZXJ0ZXIuYnVpbGQobWFwLmdldChrZXkpKSA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgZ2V0TWFwSW50MzJGb3JlaWduTWVzc2FnZU9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZU9yQnVpbGRlcj4gbWFwID0gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJGb3JlaWduTWVzc2FnZUNvbnZlcnRlci5idWlsZChtYXAuZ2V0KGtleSkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAxMDAwMCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZU1lc3NhZ2VNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSB2YWx1ZSkgewoKICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgeyB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIm1hcCB2YWx1ZSIpOyB9CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAxMDAwMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUmZ3Q7IG1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UgPSAxNzs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKAogICAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPiB2YWx1ZXMpIHsKICAgICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gZSA6IHZhbHVlcy5lbnRyeVNldCgpKSB7CiAgICAgICAgICBpZiAoZS5nZXRLZXkoKSA9PSBudWxsIHx8IGUuZ2V0VmFsdWUoKSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMkZvcmVpZ25NZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMTAwMDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlJmd0OyBtYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlID0gMTc7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZS5CdWlsZGVyIHB1dE1hcEludDMyRm9yZWlnbk1lc3NhZ2VCdWlsZGVySWZBYnNlbnQoCiAgICAgICAgICBpbnQga2V5KSB7CiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlT3JCdWlsZGVyPiBidWlsZGVyTWFwID0gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJGb3JlaWduTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXIgZW50cnkgPSBidWlsZGVyTWFwLmdldChrZXkpOwogICAgICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgICAgICBlbnRyeSA9IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZS5uZXdCdWlsZGVyKCk7CiAgICAgICAgICBidWlsZGVyTWFwLnB1dChrZXksIGVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKGVudHJ5IGluc3RhbmNlb2YgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKSB7CiAgICAgICAgICBlbnRyeSA9ICgocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKSBlbnRyeSkudG9CdWlsZGVyKCk7CiAgICAgICAgICBidWlsZGVyTWFwLnB1dChrZXksIGVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuQnVpbGRlcikgZW50cnk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RBcmVuYU1hcExpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdEFyZW5hTWFwTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RBcmVuYU1hcExpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0QXJlbmFNYXBMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RBcmVuYU1hcExpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldE1hcEZpZWxkQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNNYXBGaWVsZCgKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4KICAgIGdldE1hcEZpZWxkKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4KICAgIGdldE1hcEZpZWxkTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBnZXRNYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBnZXRNYXBGaWVsZE9yVGhyb3coCiAgICAgICAgaW50IGtleSk7CiAgfQogIC8qKgogICAqIDxwcmU+CiAgICogVGVzdCBlbWJlZGRlZCBtZXNzYWdlIHdpdGggcmVxdWlyZWQgZmllbGRzCiAgICogPC9wcmU+CiAgICoKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKQogICAgICBUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InJhd3R5cGVzIn0pCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRmllbGQoKTsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgIH0KICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUuY2xhc3MsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBNQVBfRklFTERfRklFTERfTlVNQkVSID0gMTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIE1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyIHsKICAgICAgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IGRlZmF1bHRFbnRyeSA9CiAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeQogICAgICAgICAgICAgIC48amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZV9NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsIAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLklOVDMyLAogICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLldpcmVGb3JtYXQuRmllbGRUeXBlLk1FU1NBR0UsCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gbWFwRmllbGRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4KICAgIGludGVybmFsR2V0TWFwRmllbGQoKSB7CiAgICAgIGlmIChtYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIE1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEZpZWxkXzsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0TWFwRmllbGRDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRmllbGQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEZpZWxkKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpZWxkKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0TWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IGdldE1hcEZpZWxkKCkgewogICAgICByZXR1cm4gZ2V0TWFwRmllbGRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gZ2V0TWFwRmllbGRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgZ2V0TWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXAuZ2V0KGtleSkgOiBkZWZhdWx0VmFsdWU7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgZ2V0TWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIGZvciAocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgaXRlbSA6IGdldE1hcEZpZWxkTWFwKCkudmFsdWVzKCkpIHsKICAgICAgICBpZiAoIWl0ZW0uaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0TWFwRmllbGQoKSwKICAgICAgICAgIE1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwRmllbGQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+CiAgICAgICAgbWFwRmllbGRfXyA9IE1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxLCBtYXBGaWVsZF9fKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUpKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmVxdWFscyhvYmopOwogICAgICB9CiAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBvdGhlciA9IChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUpIG9iajsKCiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBGaWVsZCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwRmllbGQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoIWludGVybmFsR2V0TWFwRmllbGQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfRklFTERfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0TWFwRmllbGQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiA8cHJlPgogICAgICogVGVzdCBlbWJlZGRlZCBtZXNzYWdlIHdpdGggcmVxdWlyZWQgZmllbGRzCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKQogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRmllbGQoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZCgpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUuY2xhc3MsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGQoKS5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBidWlsZCgpIHsKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSByZXN1bHQgPSBuZXcgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm1hcEZpZWxkXyA9IGludGVybmFsR2V0TWFwRmllbGQoKS5idWlsZChNYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEZpZWxkKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgZm9yIChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBpdGVtIDogZ2V0TWFwRmllbGRNYXAoKS52YWx1ZXMoKSkgewogICAgICAgICAgaWYgKCFpdGVtLmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAxMDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+CiAgICAgICAgICAgICAgICBtYXBGaWVsZF9fID0gaW5wdXQucmVhZE1lc3NhZ2UoCiAgICAgICAgICAgICAgICAgICAgTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGQoKS5lbnN1cmVCdWlsZGVyTWFwKCkucHV0KAogICAgICAgICAgICAgICAgICAgIG1hcEZpZWxkX18uZ2V0S2V5KCksIG1hcEZpZWxkX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTAKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwRmllbGRDb252ZXJ0ZXIgaW1wbGVtZW50cyBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlci5Db252ZXJ0ZXI8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gewogICAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgYnVpbGQocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXIgdmFsKSB7CiAgICAgICAgICBpZiAodmFsIGluc3RhbmNlb2YgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUpIHsgcmV0dXJuIChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkgdmFsOyB9CiAgICAgICAgICByZXR1cm4gKChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5CdWlsZGVyKSB2YWwpLmJ1aWxkKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPiBkZWZhdWx0RW50cnkoKSB7CiAgICAgICAgICByZXR1cm4gTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5OwogICAgICAgIH0KICAgICAgfTsKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgTWFwRmllbGRDb252ZXJ0ZXIgbWFwRmllbGRDb252ZXJ0ZXIgPSBuZXcgTWFwRmllbGRDb252ZXJ0ZXIoKTsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5CdWlsZGVyPiBtYXBGaWVsZF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuQnVpbGRlcj4KICAgICAgICAgIGludGVybmFsR2V0TWFwRmllbGQoKSB7CiAgICAgICAgaWYgKG1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPD4obWFwRmllbGRDb252ZXJ0ZXIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwRmllbGRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuQnVpbGRlcj4KICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkgewogICAgICAgIGlmIChtYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgICAgbWFwRmllbGRfID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPD4obWFwRmllbGRDb252ZXJ0ZXIpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEZpZWxkXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldE1hcEZpZWxkQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRmllbGQoKS5lbnN1cmVCdWlsZGVyTWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNNYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwRmllbGQoKS5lbnN1cmVCdWlsZGVyTWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0TWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4gZ2V0TWFwRmllbGQoKSB7CiAgICAgICAgcmV0dXJuIGdldE1hcEZpZWxkTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGU+IGdldE1hcEZpZWxkTWFwKCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEZpZWxkKCkuZ2V0SW1tdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgZ2V0TWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlT3JCdWlsZGVyPiBtYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZCgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkgPyBtYXBGaWVsZENvbnZlcnRlci5idWlsZChtYXAuZ2V0KGtleSkpIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIGdldE1hcEZpZWxkT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXI+IG1hcCA9IGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkuZW5zdXJlQnVpbGRlck1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBtYXBGaWVsZENvbnZlcnRlci5idWlsZChtYXAuZ2V0KGtleSkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyTWFwRmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGQoKS5lbnN1cmVCdWlsZGVyTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZT4KICAgICAgICAgIGdldE11dGFibGVNYXBGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkuZW5zdXJlTWVzc2FnZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlJmd0OyBtYXBfZmllbGQgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dE1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHZhbHVlKSB7CgogICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigibWFwIHZhbHVlIik7IH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZCgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSZndDsgbWFwX2ZpZWxkID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxNYXBGaWVsZCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPiB2YWx1ZXMpIHsKICAgICAgICBmb3IgKGphdmEudXRpbC5NYXAuRW50cnk8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPiBlIDogdmFsdWVzLmVudHJ5U2V0KCkpIHsKICAgICAgICAgIGlmIChlLmdldEtleSgpID09IG51bGwgfHwgZS5nZXRWYWx1ZSgpID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkKCkuZW5zdXJlQnVpbGRlck1hcCgpCiAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUmZ3Q7IG1hcF9maWVsZCA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLkJ1aWxkZXIgcHV0TWFwRmllbGRCdWlsZGVySWZBYnNlbnQoCiAgICAgICAgICBpbnQga2V5KSB7CiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXI+IGJ1aWxkZXJNYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBGaWVsZCgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZU9yQnVpbGRlciBlbnRyeSA9IGJ1aWxkZXJNYXAuZ2V0KGtleSk7CiAgICAgICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgICAgIGVudHJ5ID0gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUubmV3QnVpbGRlcigpOwogICAgICAgICAgYnVpbGRlck1hcC5wdXQoa2V5LCBlbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmIChlbnRyeSBpbnN0YW5jZW9mIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlKSB7CiAgICAgICAgICBlbnRyeSA9ICgocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUpIGVudHJ5KS50b0J1aWxkZXIoKTsKICAgICAgICAgIGJ1aWxkZXJNYXAucHV0KGtleSwgZW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLkJ1aWxkZXIpIGVudHJ5OwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdEVudW1NYXBMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBpbnQgZ2V0S25vd25NYXBGaWVsZENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zS25vd25NYXBGaWVsZCgKICAgICAgICBpbnQga2V5KTsKICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0S25vd25NYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgIGdldEtub3duTWFwRmllbGQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgIGdldEtub3duTWFwRmllbGRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBnZXRLbm93bk1hcEZpZWxkT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlICAgICAgICAgZGVmYXVsdFZhbHVlKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBnZXRLbm93bk1hcEZpZWxkT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRVbmtub3duTWFwRmllbGRDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zVW5rbm93bk1hcEZpZWxkKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRVbmtub3duTWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICBnZXRVbmtub3duTWFwRmllbGQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPgogICAgZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgICAgICAgICBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgZ2V0VW5rbm93bk1hcEZpZWxkT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdEVudW1NYXBMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSkKICAgICAgVGVzdEVudW1NYXBMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0RW51bU1hcExpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdEVudW1NYXBMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdEVudW1NYXBMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RFbnVtTWFwTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgaW50IG51bWJlcikgewogICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgIGNhc2UgMTAxOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpOwogICAgICAgIGNhc2UgMTAyOgogICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICB9CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUuY2xhc3MsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgS05PV05fTUFQX0ZJRUxEX0ZJRUxEX05VTUJFUiA9IDEwMTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNsYXNzIEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9Lbm93bk1hcEZpZWxkRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuRU5VTSwKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLlBST1RPMl9NQVBfRU5VTV9GT09fTElURS5nZXROdW1iZXIoKSk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGtub3duTWFwRmllbGRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgaWYgKGtub3duTWFwRmllbGRfID09IG51bGwpIHsKICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIGtub3duTWFwRmllbGRfOwogICAgfQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5Db252ZXJ0ZXI8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4ga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyID0KICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyLm5ld0VudW1Db252ZXJ0ZXIoCiAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUuaW50ZXJuYWxHZXRWYWx1ZU1hcCgpLAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLlBST1RPMl9NQVBfRU5VTV9GT09fTElURSk7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICBpbnRlcm5hbEdldEFkYXB0ZWRLbm93bk1hcEZpZWxkTWFwKAogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXApIHsKICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLCBqYXZhLmxhbmcuSW50ZWdlcj4oCiAgICAgICAgICAgICAgbWFwLCBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIpOwogICAgfQogICAgcHVibGljIGludCBnZXRLbm93bk1hcEZpZWxkQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc0tub3duTWFwRmllbGQoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldEtub3duTWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPgogICAgZ2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgcmV0dXJuIGdldEtub3duTWFwRmllbGRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICBnZXRLbm93bk1hcEZpZWxkTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkS25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpKTt9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldEtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkKICAgICAgICAgICAgID8ga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgZ2V0S25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIGtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBVTktOT1dOX01BUF9GSUVMRF9GSUVMRF9OVU1CRVIgPSAxMDI7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBVbmtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9Vbmtub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5FTlVNLAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUuUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFLmdldE51bWJlcigpKTsKICAgIH0KICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJzZXJpYWwiKQogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdW5rbm93bk1hcEZpZWxkXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpIHsKICAgICAgaWYgKHVua25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgIFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiB1bmtub3duTWFwRmllbGRfOwogICAgfQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwKICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5Db252ZXJ0ZXI8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4gdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIgPQogICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXIubmV3RW51bUNvbnZlcnRlcigKICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZS5pbnRlcm5hbEdldFZhbHVlTWFwKCksCiAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUuUFJPVE8yX01BUF9FTlVNX0ZPT19MSVRFKTsKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgIGludGVybmFsR2V0QWRhcHRlZFVua25vd25NYXBGaWVsZE1hcCgKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwKSB7CiAgICAgIHJldHVybiBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSwgamF2YS5sYW5nLkludGVnZXI+KAogICAgICAgICAgICAgIG1hcCwgdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIpOwogICAgfQogICAgcHVibGljIGludCBnZXRVbmtub3duTWFwRmllbGRDb3VudCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc1Vua25vd25NYXBGaWVsZCgKICAgICAgICBpbnQga2V5KSB7CgogICAgICByZXR1cm4gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgfQogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRVbmtub3duTWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlPgogICAgZ2V0VW5rbm93bk1hcEZpZWxkKCkgewogICAgICByZXR1cm4gZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICBnZXRVbmtub3duTWFwRmllbGRNYXAoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRVbmtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpKTt9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgZ2V0VW5rbm93bk1hcEZpZWxkT3JEZWZhdWx0KAogICAgICAgIGludCBrZXksCiAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkKICAgICAgICAgICAgID8gdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSkKICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldFVua25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgIC5zZXJpYWxpemVJbnRlZ2VyTWFwVG8oCiAgICAgICAgICBvdXRwdXQsCiAgICAgICAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKSwKICAgICAgICAgIEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTAxKTsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKSwKICAgICAgICAgIFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxMDIpOwogICAgICBnZXRVbmtub3duRmllbGRzKCkud3JpdGVUbyhvdXRwdXQpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0U2VyaWFsaXplZFNpemUoKSB7CiAgICAgIGludCBzaXplID0gbWVtb2l6ZWRTaXplOwogICAgICBpZiAoc2l6ZSAhPSAtMSkgcmV0dXJuIHNpemU7CgogICAgICBzaXplID0gMDsKICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICBrbm93bk1hcEZpZWxkX18gPSBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMDEsIGtub3duTWFwRmllbGRfXyk7CiAgICAgIH0KICAgICAgZm9yIChqYXZhLnV0aWwuTWFwLkVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgIHVua25vd25NYXBGaWVsZF9fID0gVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5uZXdCdWlsZGVyRm9yVHlwZSgpCiAgICAgICAgICAgIC5zZXRLZXkoZW50cnkuZ2V0S2V5KCkpCiAgICAgICAgICAgIC5zZXRWYWx1ZShlbnRyeS5nZXRWYWx1ZSgpKQogICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgICAgLmNvbXB1dGVNZXNzYWdlU2l6ZSgxMDIsIHVua25vd25NYXBGaWVsZF9fKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIG90aGVyID0gKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUpIG9iajsKCiAgICAgIGlmICghaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICghaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmICghaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgS05PV05fTUFQX0ZJRUxEX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGlmICghaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBVTktOT1dOX01BUF9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKQogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICAgIGludCBudW1iZXIpIHsKICAgICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgICAgY2FzZSAxMDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKTsKICAgICAgICAgIGNhc2UgMTAyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDEwMToKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKTsKICAgICAgICAgIGNhc2UgMTAyOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICAgIH0KICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlLmNsYXNzLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgICB9CgogICAgICAvLyBDb25zdHJ1Y3QgdXNpbmcgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmNsZWFyKCk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIGJ1aWxkKCkgewogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIHJlc3VsdCA9IG5ldyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5rbm93bk1hcEZpZWxkXyA9IGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpOwogICAgICAgICAgcmVzdWx0Lmtub3duTWFwRmllbGRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC51bmtub3duTWFwRmllbGRfID0gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKTsKICAgICAgICAgIHJlc3VsdC51bmtub3duTWFwRmllbGRfLm1ha2VJbW11dGFibGUoKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsb25lKCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyRmllbGQoZmllbGQpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJPbmVvZigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuT25lb2ZEZXNjcmlwdG9yIG9uZW9mKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmNsZWFyT25lb2Yob25lb2YpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0UmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgaW50IGluZGV4LCBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFJlcGVhdGVkRmllbGQoZmllbGQsIGluZGV4LCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBhZGRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmFkZFJlcGVhdGVkRmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2Ugb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKSB7CiAgICAgICAgICByZXR1cm4gbWVyZ2VGcm9tKChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgb3RoZXIpIHsKICAgICAgICBpZiAob3RoZXIgPT0gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSkgcmV0dXJuIHRoaXM7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLm1lcmdlRnJvbSgKICAgICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDgxMDogewogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGJ5dGVzID0gaW5wdXQucmVhZEJ5dGVzKCk7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgICAgICAgIGtub3duTWFwRmllbGRfXyA9IEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKS5wYXJzZUZyb20oYnl0ZXMpOwogICAgICAgICAgICAgICAgaWYgKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZS5mb3JOdW1iZXIoa25vd25NYXBGaWVsZF9fLmdldFZhbHVlKCkpID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgbWVyZ2VVbmtub3duTGVuZ3RoRGVsaW1pdGVkRmllbGQoMTAxLCBieXRlcyk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICAgIGtub3duTWFwRmllbGRfXy5nZXRLZXkoKSwga25vd25NYXBGaWVsZF9fLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgODEwCiAgICAgICAgICAgICAgY2FzZSA4MTg6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBieXRlcyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICB1bmtub3duTWFwRmllbGRfXyA9IFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkuZ2V0UGFyc2VyRm9yVHlwZSgpLnBhcnNlRnJvbShieXRlcyk7CiAgICAgICAgICAgICAgICBpZiAocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlLmZvck51bWJlcih1bmtub3duTWFwRmllbGRfXy5nZXRWYWx1ZSgpKSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93bkxlbmd0aERlbGltaXRlZEZpZWxkKDEwMiwgYnl0ZXMpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICAgIHVua25vd25NYXBGaWVsZF9fLmdldEtleSgpLCB1bmtub3duTWFwRmllbGRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgxOAogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIGlmICghc3VwZXIucGFyc2VVbmtub3duRmllbGQoaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5LCB0YWcpKSB7CiAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOyAvLyB3YXMgYW4gZW5kZ3JvdXAgdGFnCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGRlZmF1bHQ6CiAgICAgICAgICAgIH0gLy8gc3dpdGNoICh0YWcpCiAgICAgICAgICB9IC8vIHdoaWxlICghZG9uZSkKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnVud3JhcElPRXhjZXB0aW9uKCk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIH0gLy8gZmluYWxseQogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGtub3duTWFwRmllbGRfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkgewogICAgICAgIGlmIChrbm93bk1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGtub3duTWFwRmllbGRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkgewogICAgICAgIGlmIChrbm93bk1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgICBrbm93bk1hcEZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgS25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIWtub3duTWFwRmllbGRfLmlzTXV0YWJsZSgpKSB7CiAgICAgICAgICBrbm93bk1hcEZpZWxkXyA9IGtub3duTWFwRmllbGRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkXzsKICAgICAgfQogICAgICBwdWJsaWMgaW50IGdldEtub3duTWFwRmllbGRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNLbm93bk1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0S25vd25NYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgICAgZ2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgICByZXR1cm4gZ2V0S25vd25NYXBGaWVsZE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4KICAgICAgZ2V0S25vd25NYXBGaWVsZE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkS25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkpO30KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldEtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpCiAgICAgICAgICAgICAgID8ga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSBnZXRLbm93bk1hcEZpZWxkT3JUaHJvdygKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJLbm93bk1hcEZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDAxKTsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZUtub3duTWFwRmllbGQoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICAgICAgICBnZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZEtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRLbm93bk1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSB2YWx1ZSkgewoKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvQmFja3dhcmQodmFsdWUpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0QWxsS25vd25NYXBGaWVsZCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRBZGFwdGVkS25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKSkKICAgICAgICAgICAgICAgIC5wdXRBbGwodmFsdWVzKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gdW5rbm93bk1hcEZpZWxkXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkgewogICAgICAgIGlmICh1bmtub3duTWFwRmllbGRfID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLmVtcHR5TWFwRmllbGQoCiAgICAgICAgICAgICAgVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB1bmtub3duTWFwRmllbGRfOwogICAgICB9CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKSB7CiAgICAgICAgaWYgKHVua25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgICAgdW5rbm93bk1hcEZpZWxkXyA9IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQubmV3TWFwRmllbGQoCiAgICAgICAgICAgICAgVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIGlmICghdW5rbm93bk1hcEZpZWxkXy5pc011dGFibGUoKSkgewogICAgICAgICAgdW5rbm93bk1hcEZpZWxkXyA9IHVua25vd25NYXBGaWVsZF8uY29weSgpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHVua25vd25NYXBGaWVsZF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRVbmtub3duTWFwRmllbGRDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zVW5rbm93bk1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5jb250YWluc0tleShrZXkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2Uge0BsaW5rICNnZXRVbmtub3duTWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICAgIGdldFVua25vd25NYXBGaWVsZCgpIHsKICAgICAgICByZXR1cm4gZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICAgIGdldFVua25vd25NYXBGaWVsZE1hcCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkVW5rbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpKTt9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldFVua25vd25NYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgICA/IHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlIGdldFVua25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICAgIGlmICghbWFwLmNvbnRhaW5zS2V5KGtleSkpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB1bmtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKTsKICAgICAgfQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhclVua25vd25NYXBGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcmVtb3ZlVW5rbm93bk1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnJlbW92ZShrZXkpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBVc2UgYWx0ZXJuYXRlIG11dGF0aW9uIGFjY2Vzc29ycyBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGU+CiAgICAgICAgICBnZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkVW5rbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dFVua25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9CYWNrd2FyZCh2YWx1ZSkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbFVua25vd25NYXBGaWVsZCgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtTGl0ZT4gdmFsdWVzKSB7CiAgICAgICAgaW50ZXJuYWxHZXRBZGFwdGVkVW5rbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkpCiAgICAgICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKQogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogICAgQGphdmEubGFuZy5EZXByZWNhdGVkIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVudW1NYXBMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPFRlc3RFbnVtTWFwTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RFbnVtTWFwTGl0ZSBwYXJzZVBhcnRpYWxGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ld0J1aWxkZXIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgYnVpbGRlci5tZXJnZUZyb20oaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuVW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5hc0ludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbigpLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0gY2F0Y2ggKGphdmEuaW8uSU9FeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKGUpCiAgICAgICAgICAgICAgLnNldFVuZmluaXNoZWRNZXNzYWdlKGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVpbGRlci5idWlsZFBhcnRpYWwoKTsKICAgICAgfQogICAgfTsKCiAgICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbnVtTWFwTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0RW51bU1hcExpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0U7CiAgICB9CgogIH0KCiAgcHVibGljIGludGVyZmFjZSBUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKQogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPckJ1aWxkZXIgewoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRLbm93bk1hcEZpZWxkQ291bnQoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNLbm93bk1hcEZpZWxkKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRLbm93bk1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0S25vd25NYXBGaWVsZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAqLwogICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0S25vd25NYXBGaWVsZE1hcCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGdldEtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgICAgICAgICBkZWZhdWx0VmFsdWUpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAqLwogICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGdldEtub3duTWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpOwoKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgaW50IGdldFVua25vd25NYXBGaWVsZENvdW50KCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIGJvb2xlYW4gY29udGFpbnNVbmtub3duTWFwRmllbGQoCiAgICAgICAgaW50IGtleSk7CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldFVua25vd25NYXBGaWVsZE1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgIGdldFVua25vd25NYXBGaWVsZCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICBnZXRVbmtub3duTWFwRmllbGRNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGdldFVua25vd25NYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSAgICAgICAgIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgKi8KICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpOwogIH0KICAvKioKICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKQogICAgICBUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUoY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlcjw/PiBidWlsZGVyKSB7CiAgICAgIHN1cGVyKGJ1aWxkZXIpOwogICAgfQogICAgcHJpdmF0ZSBUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfZGVzY3JpcHRvcjsKICAgIH0KCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InJhd3R5cGVzIn0pCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgY2FzZSAxMDE6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCk7CiAgICAgICAgY2FzZSAxMDI6CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKTsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgIH0KICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5jbGFzcywgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBLTk9XTl9NQVBfRklFTERfRklFTERfTlVNQkVSID0gMTAxOwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgS25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlciB7CiAgICAgIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj5uZXdEZWZhdWx0SW5zdGFuY2UoCiAgICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX0tub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5FTlVNLAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUuRV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUuZ2V0TnVtYmVyKCkpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBrbm93bk1hcEZpZWxkXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKSB7CiAgICAgIGlmIChrbm93bk1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgS25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICB9CiAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkXzsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGZpbmFsCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXIuQ29udmVydGVyPAogICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+IGtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlciA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5uZXdFbnVtQ29udmVydGVyKAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlLmludGVybmFsR2V0VmFsdWVNYXAoKSwKICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZS5FX1BST1RPMl9NQVBfRU5VTV9GT09fTElURSk7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICBpbnRlcm5hbEdldEFkYXB0ZWRLbm93bk1hcEZpZWxkTWFwKAogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXApIHsKICAgICAgcmV0dXJuIG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludGVybmFsLk1hcEFkYXB0ZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlLCBqYXZhLmxhbmcuSW50ZWdlcj4oCiAgICAgICAgICAgICAgbWFwLCBrbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIpOwogICAgfQogICAgcHVibGljIGludCBnZXRLbm93bk1hcEZpZWxkQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc0tub3duTWFwRmllbGQoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldEtub3duTWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgcmV0dXJuIGdldEtub3duTWFwRmllbGRNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICBnZXRLbm93bk1hcEZpZWxkTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkS25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpKTt9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGdldEtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkKICAgICAgICAgICAgID8ga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZ2V0S25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgaW50IGtleSkgewoKICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIGtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBVTktOT1dOX01BUF9GSUVMRF9GSUVMRF9OVU1CRVIgPSAxMDI7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBVbmtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gZGVmYXVsdEVudHJ5ID0KICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5CiAgICAgICAgICAgICAgLjxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+bmV3RGVmYXVsdEluc3RhbmNlKAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9Vbmtub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yLCAKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5JTlQzMiwKICAgICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5XaXJlRm9ybWF0LkZpZWxkVHlwZS5FTlVNLAogICAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUuRV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEUuZ2V0TnVtYmVyKCkpOwogICAgfQogICAgQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCiAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiB1bmtub3duTWFwRmllbGRfOwogICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkgewogICAgICBpZiAodW5rbm93bk1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgVW5rbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHVua25vd25NYXBGaWVsZF87CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnRlcm5hbC5NYXBBZGFwdGVyLkNvbnZlcnRlcjwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPiB1bmtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlciA9CiAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlci5uZXdFbnVtQ29udmVydGVyKAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlLmludGVybmFsR2V0VmFsdWVNYXAoKSwKICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZS5FX1BST1RPMl9NQVBfRU5VTV9GT09fTElURSk7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICBpbnRlcm5hbEdldEFkYXB0ZWRVbmtub3duTWFwRmllbGRNYXAoCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCkgewogICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuSW50ZXJuYWwuTWFwQWRhcHRlcjwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUsIGphdmEubGFuZy5JbnRlZ2VyPigKICAgICAgICAgICAgICBtYXAsIHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyKTsKICAgIH0KICAgIHB1YmxpYyBpbnQgZ2V0VW5rbm93bk1hcEZpZWxkQ291bnQoKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpLnNpemUoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gY29udGFpbnNVbmtub3duTWFwRmllbGQoCiAgICAgICAgaW50IGtleSkgewoKICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgIH0KICAgIC8qKgogICAgICogVXNlIHtAbGluayAjZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZT4KICAgIGdldFVua25vd25NYXBGaWVsZCgpIHsKICAgICAgcmV0dXJuIGdldFVua25vd25NYXBGaWVsZE1hcCgpOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRBZGFwdGVkVW5rbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKSk7fQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGdldFVua25vd25NYXBGaWVsZE9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpCiAgICAgICAgICAgICA/IHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpCiAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgaWYgKCFtYXAuY29udGFpbnNLZXkoa2V5KSkgewogICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCksCiAgICAgICAgICBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSwKICAgICAgICAgIDEwMSk7CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgLnNlcmlhbGl6ZUludGVnZXJNYXBUbygKICAgICAgICAgIG91dHB1dCwKICAgICAgICAgIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCksCiAgICAgICAgICBVbmtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LAogICAgICAgICAgMTAyKTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKS5lbnRyeVNldCgpKSB7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAga25vd25NYXBGaWVsZF9fID0gS25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTAxLCBrbm93bk1hcEZpZWxkX18pOwogICAgICB9CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IGVudHJ5CiAgICAgICAgICAgOiBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmVudHJ5U2V0KCkpIHsKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICB1bmtub3duTWFwRmllbGRfXyA9IFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkubmV3QnVpbGRlckZvclR5cGUoKQogICAgICAgICAgICAuc2V0S2V5KGVudHJ5LmdldEtleSgpKQogICAgICAgICAgICAuc2V0VmFsdWUoZW50cnkuZ2V0VmFsdWUoKSkKICAgICAgICAgICAgLmJ1aWxkKCk7CiAgICAgICAgc2l6ZSArPSBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtCiAgICAgICAgICAgIC5jb21wdXRlTWVzc2FnZVNpemUoMTAyLCB1bmtub3duTWFwRmllbGRfXyk7CiAgICAgIH0KICAgICAgc2l6ZSArPSBnZXRVbmtub3duRmllbGRzKCkuZ2V0U2VyaWFsaXplZFNpemUoKTsKICAgICAgbWVtb2l6ZWRTaXplID0gc2l6ZTsKICAgICAgcmV0dXJuIHNpemU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKGZpbmFsIGphdmEubGFuZy5PYmplY3Qgb2JqKSB7CiAgICAgIGlmIChvYmogPT0gdGhpcykgewogICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBvdGhlciA9IChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlKSBvYmo7CgogICAgICBpZiAoIWludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmVxdWFscygKICAgICAgICAgIG90aGVyLmludGVybmFsR2V0S25vd25NYXBGaWVsZCgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZXF1YWxzKAogICAgICAgICAgb3RoZXIuaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKSkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoIWludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmlzRW1wdHkoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEtOT1dOX01BUF9GSUVMRF9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBpZiAoIWludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgVU5LTk9XTl9NQVBfRklFTERfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuaGFzaENvZGUoKTsKICAgICAgfQogICAgICBoYXNoID0gKDI5ICogaGFzaCkgKyBnZXRVbmtub3duRmllbGRzKCkuaGFzaENvZGUoKTsKICAgICAgbWVtb2l6ZWRIYXNoQ29kZSA9IGhhc2g7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5uaW8uQnl0ZUJ1ZmZlciBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgYnl0ZVtdIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbShqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRGVsaW1pdGVkRnJvbSgKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VEZWxpbWl0ZWRXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzCiAgICAgICAgICAucGFyc2VXaXRoSU9FeGNlcHRpb24oUEFSU0VSLCBpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKCkgeyByZXR1cm4gbmV3QnVpbGRlcigpOyB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcigpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIEJ1aWxkZXIgbmV3QnVpbGRlcihwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHByb3RvdHlwZSkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKS5tZXJnZUZyb20ocHJvdG90eXBlKTsKICAgIH0KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBCdWlsZGVyIHRvQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMgPT0gREVGQVVMVF9JTlNUQU5DRQogICAgICAgICAgPyBuZXcgQnVpbGRlcigpIDogbmV3IEJ1aWxkZXIoKS5tZXJnZUZyb20odGhpcyk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3IEJ1aWxkZXIocGFyZW50KTsKICAgICAgcmV0dXJuIGJ1aWxkZXI7CiAgICB9CiAgICAvKioKICAgICAqIFByb3RvYnVmIHR5cGUge0Bjb2RlIHByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSkKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlT3JCdWlsZGVyIHsKICAgICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgICBpbnQgbnVtYmVyKSB7CiAgICAgICAgc3dpdGNoIChudW1iZXIpIHsKICAgICAgICAgIGNhc2UgMTAxOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRLbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICBjYXNlIDEwMjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJJbnZhbGlkIG1hcCBmaWVsZCBudW1iZXI6ICIgKyBudW1iZXIpOwogICAgICAgIH0KICAgICAgfQogICAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InJhd3R5cGVzIn0pCiAgICAgIHByb3RlY3RlZCBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkUmVmbGVjdGlvbkFjY2Vzc29yIGludGVybmFsR2V0TXV0YWJsZU1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICAgIGludCBudW1iZXIpIHsKICAgICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgICAgY2FzZSAxMDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICBjYXNlIDEwMjoKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICBpbnRlcm5hbEdldEZpZWxkQWNjZXNzb3JUYWJsZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5jbGFzcywgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5CdWlsZGVyLmNsYXNzKTsKICAgICAgfQoKICAgICAgLy8gQ29uc3RydWN0IHVzaW5nIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5jbGVhcigpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBidWlsZCgpIHsKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSByZXN1bHQgPSBuZXcgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQua25vd25NYXBGaWVsZF8gPSBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKTsKICAgICAgICAgIHJlc3VsdC5rbm93bk1hcEZpZWxkXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQudW5rbm93bk1hcEZpZWxkXyA9IGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCk7CiAgICAgICAgICByZXN1bHQudW5rbm93bk1hcEZpZWxkXy5tYWtlSW1tdXRhYmxlKCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSlvdGhlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN1cGVyLm1lcmdlRnJvbShvdGhlcik7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbShwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0S25vd25NYXBGaWVsZCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkubWVyZ2VGcm9tKAogICAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4MTA6IHsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBieXRlcyA9IGlucHV0LnJlYWRCeXRlcygpOwogICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICAgICAgICBrbm93bk1hcEZpZWxkX18gPSBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeS5nZXRQYXJzZXJGb3JUeXBlKCkucGFyc2VGcm9tKGJ5dGVzKTsKICAgICAgICAgICAgICAgIGlmIChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUuZm9yTnVtYmVyKGtub3duTWFwRmllbGRfXy5nZXRWYWx1ZSgpKSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIG1lcmdlVW5rbm93bkxlbmd0aERlbGltaXRlZEZpZWxkKDEwMSwgYnl0ZXMpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgICBrbm93bk1hcEZpZWxkX18uZ2V0S2V5KCksIGtub3duTWFwRmllbGRfXy5nZXRWYWx1ZSgpKTsKICAgICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgxMAogICAgICAgICAgICAgIGNhc2UgODE4OiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgYnl0ZXMgPSBpbnB1dC5yZWFkQnl0ZXMoKTsKICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgICAgICAgdW5rbm93bk1hcEZpZWxkX18gPSBVbmtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKS5wYXJzZUZyb20oYnl0ZXMpOwogICAgICAgICAgICAgICAgaWYgKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZS5mb3JOdW1iZXIodW5rbm93bk1hcEZpZWxkX18uZ2V0VmFsdWUoKSkgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBtZXJnZVVua25vd25MZW5ndGhEZWxpbWl0ZWRGaWVsZCgxMDIsIGJ5dGVzKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKS5wdXQoCiAgICAgICAgICAgICAgICAgICAgICB1bmtub3duTWFwRmllbGRfXy5nZXRLZXkoKSwgdW5rbm93bk1hcEZpZWxkX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gY2FzZSA4MTgKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPAogICAgICAgICAgamF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBrbm93bk1hcEZpZWxkXzsKICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4KICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpIHsKICAgICAgICBpZiAoa25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgICBLbm93bk1hcEZpZWxkRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBrbm93bk1hcEZpZWxkXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpIHsKICAgICAgICBpZiAoa25vd25NYXBGaWVsZF8gPT0gbnVsbCkgewogICAgICAgICAga25vd25NYXBGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIEtub3duTWFwRmllbGREZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKCFrbm93bk1hcEZpZWxkXy5pc011dGFibGUoKSkgewogICAgICAgICAga25vd25NYXBGaWVsZF8gPSBrbm93bk1hcEZpZWxkXy5jb3B5KCk7CiAgICAgICAgfQogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4ga25vd25NYXBGaWVsZF87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRLbm93bk1hcEZpZWxkQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLnNpemUoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zS25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldEtub3duTWFwRmllbGRNYXAoKX0gaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICAgIGdldEtub3duTWFwRmllbGQoKSB7CiAgICAgICAgcmV0dXJuIGdldEtub3duTWFwRmllbGRNYXAoKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+CiAgICAgIGdldEtub3duTWFwRmllbGRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZEtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpKTt9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRLbm93bk1hcEZpZWxkT3JEZWZhdWx0KAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBkZWZhdWx0VmFsdWUpIHsKCiAgICAgICAgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IG1hcCA9CiAgICAgICAgICAgIGludGVybmFsR2V0S25vd25NYXBGaWVsZCgpLmdldE1hcCgpOwogICAgICAgIHJldHVybiBtYXAuY29udGFpbnNLZXkoa2V5KQogICAgICAgICAgICAgICA/IGtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKQogICAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgZ2V0S25vd25NYXBGaWVsZE9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPiBtYXAgPQogICAgICAgICAgICBpbnRlcm5hbEdldEtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4ga25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvRm9yd2FyZChtYXAuZ2V0KGtleSkpOwogICAgICB9CiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyS25vd25NYXBGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IGtub3duX21hcF9maWVsZCA9IDEwMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVLbm93bk1hcEZpZWxkKAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVLbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgICAgICAgZ2V0TXV0YWJsZUtub3duTWFwRmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiBpbnRlcm5hbEdldEFkYXB0ZWRLbm93bk1hcEZpZWxkTWFwKAogICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlS25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyBrbm93bl9tYXBfZmllbGQgPSAxMDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0S25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUgdmFsdWUpIHsKCgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIGtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0JhY2t3YXJkKHZhbHVlKSk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsga25vd25fbWFwX2ZpZWxkID0gMTAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbEtub3duTWFwRmllbGQoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0QWRhcHRlZEtub3duTWFwRmllbGRNYXAoCiAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZUtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkpCiAgICAgICAgICAgICAgICAucHV0QWxsKHZhbHVlcyk7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+IHVua25vd25NYXBGaWVsZF87CiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgamF2YS5sYW5nLkludGVnZXI+CiAgICAgICAgICBpbnRlcm5hbEdldFVua25vd25NYXBGaWVsZCgpIHsKICAgICAgICBpZiAodW5rbm93bk1hcEZpZWxkXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZC5lbXB0eU1hcEZpZWxkKAogICAgICAgICAgICAgIFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdW5rbm93bk1hcEZpZWxkXzsKICAgICAgfQogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQ8amF2YS5sYW5nLkludGVnZXIsIGphdmEubGFuZy5JbnRlZ2VyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkgewogICAgICAgIGlmICh1bmtub3duTWFwRmllbGRfID09IG51bGwpIHsKICAgICAgICAgIHVua25vd25NYXBGaWVsZF8gPSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkLm5ld01hcEZpZWxkKAogICAgICAgICAgICAgIFVua25vd25NYXBGaWVsZERlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgICBpZiAoIXVua25vd25NYXBGaWVsZF8uaXNNdXRhYmxlKCkpIHsKICAgICAgICAgIHVua25vd25NYXBGaWVsZF8gPSB1bmtub3duTWFwRmllbGRfLmNvcHkoKTsKICAgICAgICB9CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB1bmtub3duTWFwRmllbGRfOwogICAgICB9CiAgICAgIHB1YmxpYyBpbnQgZ2V0VW5rbm93bk1hcEZpZWxkQ291bnQoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc1Vua25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0VW5rbm93bk1hcEZpZWxkKCkuZ2V0TWFwKCkuY29udGFpbnNLZXkoa2V5KTsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIHtAbGluayAjZ2V0VW5rbm93bk1hcEZpZWxkTWFwKCl9IGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgICBnZXRVbmtub3duTWFwRmllbGQoKSB7CiAgICAgICAgcmV0dXJuIGdldFVua25vd25NYXBGaWVsZE1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSZndDsgdW5rbm93bl9tYXBfZmllbGQgPSAxMDI7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgICBnZXRVbmtub3duTWFwRmllbGRNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZFVua25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKSk7fQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIC8qIG51bGxhYmxlICovCnByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPckRlZmF1bHQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgLyogbnVsbGFibGUgKi8KcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgICByZXR1cm4gbWFwLmNvbnRhaW5zS2V5KGtleSkKICAgICAgICAgICAgICAgPyB1bmtub3duTWFwRmllbGRWYWx1ZUNvbnZlcnRlci5kb0ZvcndhcmQobWFwLmdldChrZXkpKQogICAgICAgICAgICAgICA6IGRlZmF1bHRWYWx1ZTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Qcm90bzJNYXBFbnVtUGx1c0V4dHJhTGl0ZSBnZXRVbmtub3duTWFwRmllbGRPclRocm93KAogICAgICAgICAgaW50IGtleSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBqYXZhLmxhbmcuSW50ZWdlcj4gbWFwID0KICAgICAgICAgICAgaW50ZXJuYWxHZXRVbmtub3duTWFwRmllbGQoKS5nZXRNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdW5rbm93bk1hcEZpZWxkVmFsdWVDb252ZXJ0ZXIuZG9Gb3J3YXJkKG1hcC5nZXQoa2V5KSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJVbmtub3duTWFwRmllbGQoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDIpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKQogICAgICAgICAgICAuY2xlYXIoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGUmZ3Q7IHVua25vd25fbWFwX2ZpZWxkID0gMTAyOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHJlbW92ZVVua25vd25NYXBGaWVsZCgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpCiAgICAgICAgICAgIC5yZW1vdmUoa2V5KTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogVXNlIGFsdGVybmF0ZSBtdXRhdGlvbiBhY2Nlc3NvcnMgaW5zdGVhZC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZAogICAgICBwdWJsaWMgamF2YS51dGlsLk1hcDxqYXZhLmxhbmcuSW50ZWdlciwgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlPgogICAgICAgICAgZ2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpIHsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0QWRhcHRlZFVua25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgIGludGVybmFsR2V0TXV0YWJsZVVua25vd25NYXBGaWVsZCgpLmdldE11dGFibGVNYXAoKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRVbmtub3duTWFwRmllbGQoCiAgICAgICAgICBpbnQga2V5LAogICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlIHZhbHVlKSB7CgoKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVVbmtub3duTWFwRmllbGQoKS5nZXRNdXRhYmxlTWFwKCkKICAgICAgICAgICAgLnB1dChrZXksIHVua25vd25NYXBGaWVsZFZhbHVlQ29udmVydGVyLmRvQmFja3dhcmQodmFsdWUpKTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1QbHVzRXh0cmFMaXRlJmd0OyB1bmtub3duX21hcF9maWVsZCA9IDEwMjs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBwdXRBbGxVbmtub3duTWFwRmllbGQoCiAgICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU+IHZhbHVlcykgewogICAgICAgIGludGVybmFsR2V0QWRhcHRlZFVua25vd25NYXBGaWVsZE1hcCgKICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlVW5rbm93bk1hcEZpZWxkKCkuZ2V0TXV0YWJsZU1hcCgpKQogICAgICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIHNldFVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldFVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgbWVyZ2VVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5tZXJnZVVua25vd25GaWVsZHModW5rbm93bkZpZWxkcyk7CiAgICAgIH0KCgogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUpCiAgICB9CgogICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGNsYXNzX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgREVGQVVMVF9JTlNUQU5DRTsKICAgIHN0YXRpYyB7CiAgICAgIERFRkFVTFRfSU5TVEFOQ0UgPSBuZXcgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZT4KICAgICAgICBQQVJTRVIgPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5BYnN0cmFjdFBhcnNlcjxUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGU+KCkgewogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0RW51bU1hcFBsdXNFeHRyYUxpdGU+IHBhcnNlcigpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlPiBnZXRQYXJzZXJGb3JUeXBlKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgVGVzdE1lc3NhZ2VNYXBMaXRlT3JCdWlsZGVyIGV4dGVuZHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGludGVyZmFjZV9leHRlbmRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGludCBnZXRNYXBJbnQzMk1lc3NhZ2VDb3VudCgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICovCiAgICBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJNZXNzYWdlKAogICAgICAgIGludCBrZXkpOwogICAgLyoqCiAgICAgKiBVc2Uge0BsaW5rICNnZXRNYXBJbnQzMk1lc3NhZ2VNYXAoKX0gaW5zdGVhZC4KICAgICAqLwogICAgQGphdmEubGFuZy5EZXByZWNhdGVkCiAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPgogICAgZ2V0TWFwSW50MzJNZXNzYWdlKCk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+CiAgICBnZXRNYXBJbnQzMk1lc3NhZ2VNYXAoKTsKICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAqLwogICAgLyogbnVsbGFibGUgKi8KY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRNYXBJbnQzMk1lc3NhZ2VPckRlZmF1bHQoCiAgICAgICAgaW50IGtleSwKICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGRlZmF1bHRWYWx1ZSk7CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZ2V0TWFwSW50MzJNZXNzYWdlT3JUaHJvdygKICAgICAgICBpbnQga2V5KTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlfQogICAqLwogIHB1YmxpYyBzdGF0aWMgZmluYWwgY2xhc3MgVGVzdE1lc3NhZ2VNYXBMaXRlIGV4dGVuZHMKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMgaW1wbGVtZW50cwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQobWVzc2FnZV9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSkKICAgICAgVGVzdE1lc3NhZ2VNYXBMaXRlT3JCdWlsZGVyIHsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAwTDsKICAgIC8vIFVzZSBUZXN0TWVzc2FnZU1hcExpdGUubmV3QnVpbGRlcigpIHRvIGNvbnN0cnVjdC4KICAgIHByaXZhdGUgVGVzdE1lc3NhZ2VNYXBMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdE1lc3NhZ2VNYXBMaXRlKCkgewogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsidW51c2VkIn0pCiAgICBwcm90ZWN0ZWQgamF2YS5sYW5nLk9iamVjdCBuZXdJbnN0YW5jZSgKICAgICAgICBVbnVzZWRQcml2YXRlUGFyYW1ldGVyIHVudXNlZCkgewogICAgICByZXR1cm4gbmV3IFRlc3RNZXNzYWdlTWFwTGl0ZSgpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNYXBGaWVsZFJlZmxlY3Rpb24oCiAgICAgICAgaW50IG51bWJlcikgewogICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAiSW52YWxpZCBtYXAgZmllbGQgbnVtYmVyOiAiICsgbnVtYmVyKTsKICAgICAgfQogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlLmNsYXNzLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IE1BUF9JTlQzMl9NRVNTQUdFX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBNYXBJbnQzMk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIgewogICAgICBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBFbnRyeTwKICAgICAgICAgIGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBkZWZhdWx0RW50cnkgPQogICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnkKICAgICAgICAgICAgICAuPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPm5ld0RlZmF1bHRJbnN0YW5jZSgKICAgICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfTWFwSW50MzJNZXNzYWdlRW50cnlfZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuSU5UMzIsCiAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuV2lyZUZvcm1hdC5GaWVsZFR5cGUuTUVTU0FHRSwKICAgICAgICAgICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSk7CiAgICB9CiAgICBAU3VwcHJlc3NXYXJuaW5ncygic2VyaWFsIikKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDwKICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gbWFwSW50MzJNZXNzYWdlXzsKICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZDxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4KICAgIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkgewogICAgICBpZiAobWFwSW50MzJNZXNzYWdlXyA9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGQuZW1wdHlNYXBGaWVsZCgKICAgICAgICAgICAgTWFwSW50MzJNZXNzYWdlRGVmYXVsdEVudHJ5SG9sZGVyLmRlZmF1bHRFbnRyeSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG1hcEludDMyTWVzc2FnZV87CiAgICB9CiAgICBwdWJsaWMgaW50IGdldE1hcEludDMyTWVzc2FnZUNvdW50KCkgewogICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5nZXRNYXAoKS5zaXplKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGNvbnRhaW5zTWFwSW50MzJNZXNzYWdlKAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIHJldHVybiBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpLmdldE1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICB9CiAgICAvKioKICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyTWVzc2FnZU1hcCgpfSBpbnN0ZWFkLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRNYXBJbnQzMk1lc3NhZ2UoKSB7CiAgICAgIHJldHVybiBnZXRNYXBJbnQzMk1lc3NhZ2VNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldE1hcEludDMyTWVzc2FnZU1hcCgpIHsKICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZ2V0TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE1hcEludDMyTWVzc2FnZU9yRGVmYXVsdCgKICAgICAgICBpbnQga2V5LAogICAgICAgIC8qIG51bGxhYmxlICovCmNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgZGVmYXVsdFZhbHVlKSB7CgogICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBtYXAgPQogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5nZXRNYXAoKTsKICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwLmdldChrZXkpIDogZGVmYXVsdFZhbHVlOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSBnZXRNYXBJbnQzMk1lc3NhZ2VPclRocm93KAogICAgICAgIGludCBrZXkpIHsKCiAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IG1hcCA9CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpLmdldE1hcCgpOwogICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgdGhyb3cgbmV3IGphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgfQogICAgICByZXR1cm4gbWFwLmdldChrZXkpOwogICAgfQoKICAgIHByaXZhdGUgYnl0ZSBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAtMTsKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgIGJ5dGUgaXNJbml0aWFsaXplZCA9IG1lbW9pemVkSXNJbml0aWFsaXplZDsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMSkgcmV0dXJuIHRydWU7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDApIHJldHVybiBmYWxzZTsKCiAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIHdyaXRlVG8oY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbSBvdXRwdXQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAuc2VyaWFsaXplSW50ZWdlck1hcFRvKAogICAgICAgICAgb3V0cHV0LAogICAgICAgICAgaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKSwKICAgICAgICAgIE1hcEludDMyTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnksCiAgICAgICAgICAxKTsKICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZW50cnkKICAgICAgICAgICA6IGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZ2V0TWFwKCkuZW50cnlTZXQoKSkgewogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+CiAgICAgICAgbWFwSW50MzJNZXNzYWdlX18gPSBNYXBJbnQzMk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5Lm5ld0J1aWxkZXJGb3JUeXBlKCkKICAgICAgICAgICAgLnNldEtleShlbnRyeS5nZXRLZXkoKSkKICAgICAgICAgICAgLnNldFZhbHVlKGVudHJ5LmdldFZhbHVlKCkpCiAgICAgICAgICAgIC5idWlsZCgpOwogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgICAuY29tcHV0ZU1lc3NhZ2VTaXplKDEsIG1hcEludDMyTWVzc2FnZV9fKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKSkgewogICAgICAgIHJldHVybiBzdXBlci5lcXVhbHMob2JqKTsKICAgICAgfQogICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIG90aGVyID0gKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUpIG9iajsKCiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5lcXVhbHMoCiAgICAgICAgICBvdGhlci5pbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpKSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoIWdldFVua25vd25GaWVsZHMoKS5lcXVhbHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKSkgcmV0dXJuIGZhbHNlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICBpZiAobWVtb2l6ZWRIYXNoQ29kZSAhPSAwKSB7CiAgICAgICAgcmV0dXJuIG1lbW9pemVkSGFzaENvZGU7CiAgICAgIH0KICAgICAgaW50IGhhc2ggPSA0MTsKICAgICAgaGFzaCA9ICgxOSAqIGhhc2gpICsgZ2V0RGVzY3JpcHRvcigpLmhhc2hDb2RlKCk7CiAgICAgIGlmICghaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5nZXRNYXAoKS5pc0VtcHR5KCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBNQVBfSU5UMzJfTUVTU0FHRV9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5oYXNoQ29kZSgpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKGJ5dGVbXSBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlfQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIEJ1aWxkZXIgZXh0ZW5kcwogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8QnVpbGRlcj4gaW1wbGVtZW50cwogICAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKQogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvcjsKICAgICAgfQoKICAgICAgQFN1cHByZXNzV2FybmluZ3MoeyJyYXd0eXBlcyJ9KQogICAgICBwcm90ZWN0ZWQgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZFJlZmxlY3Rpb25BY2Nlc3NvciBpbnRlcm5hbEdldE1hcEZpZWxkUmVmbGVjdGlvbigKICAgICAgICAgIGludCBudW1iZXIpIHsKICAgICAgICBzd2l0Y2ggKG51bWJlcikgewogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKHsicmF3dHlwZXMifSkKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRSZWZsZWN0aW9uQWNjZXNzb3IgaW50ZXJuYWxHZXRNdXRhYmxlTWFwRmllbGRSZWZsZWN0aW9uKAogICAgICAgICAgaW50IG51bWJlcikgewogICAgICAgIHN3aXRjaCAobnVtYmVyKSB7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIkludmFsaWQgbWFwIGZpZWxkIG51bWJlcjogIiArIG51bWJlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgICAuZW5zdXJlRmllbGRBY2Nlc3NvcnNJbml0aWFsaXplZCgKICAgICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUuY2xhc3MsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlLm5ld0J1aWxkZXIoKQogICAgICBwcml2YXRlIEJ1aWxkZXIoKSB7CgogICAgICB9CgogICAgICBwcml2YXRlIEJ1aWxkZXIoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICAgIHN1cGVyKHBhcmVudCk7CgogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXIoKSB7CiAgICAgICAgc3VwZXIuY2xlYXIoKTsKICAgICAgICBiaXRGaWVsZDBfID0gMDsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5jbGVhcigpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICAgIGdldERlc2NyaXB0b3JGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCk7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgYnVpbGQoKSB7CiAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSByZXN1bHQgPSBidWlsZFBhcnRpYWwoKTsKICAgICAgICBpZiAoIXJlc3VsdC5pc0luaXRpYWxpemVkKCkpIHsKICAgICAgICAgIHRocm93IG5ld1VuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgYnVpbGRQYXJ0aWFsKCkgewogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgcmVzdWx0ID0gbmV3IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUodGhpcyk7CiAgICAgICAgaWYgKGJpdEZpZWxkMF8gIT0gMCkgeyBidWlsZFBhcnRpYWwwKHJlc3VsdCk7IH0KICAgICAgICBvbkJ1aWx0KCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgcHJpdmF0ZSB2b2lkIGJ1aWxkUGFydGlhbDAocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSByZXN1bHQpIHsKICAgICAgICBpbnQgZnJvbV9iaXRGaWVsZDBfID0gYml0RmllbGQwXzsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0Lm1hcEludDMyTWVzc2FnZV8gPSBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpLmJ1aWxkKE1hcEludDMyTWVzc2FnZURlZmF1bHRFbnRyeUhvbGRlci5kZWZhdWx0RW50cnkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUpb3RoZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdXBlci5tZXJnZUZyb20ob3RoZXIpOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICB9CgogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20ocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5tZXJnZUZyb20oCiAgICAgICAgICAgIG90aGVyLmludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDEwOiB7CiAgICAgICAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEVudHJ5PGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPgogICAgICAgICAgICAgICAgbWFwSW50MzJNZXNzYWdlX18gPSBpbnB1dC5yZWFkTWVzc2FnZSgKICAgICAgICAgICAgICAgICAgICBNYXBJbnQzMk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5LmdldFBhcnNlckZvclR5cGUoKSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpLnB1dCgKICAgICAgICAgICAgICAgICAgICBtYXBJbnQzMk1lc3NhZ2VfXy5nZXRLZXkoKSwgbWFwSW50MzJNZXNzYWdlX18uZ2V0VmFsdWUoKSk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTAKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2xhc3MgTWFwSW50MzJNZXNzYWdlQ29udmVydGVyIGltcGxlbWVudHMgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXIuQ29udmVydGVyPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiB7CiAgICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGJ1aWxkKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXIgdmFsKSB7CiAgICAgICAgICBpZiAodmFsIGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgeyByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIHZhbDsgfQogICAgICAgICAgcmV0dXJuICgoY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyKSB2YWwpLmJ1aWxkKCk7CiAgICAgICAgfQoKICAgICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRW50cnk8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGRlZmF1bHRFbnRyeSgpIHsKICAgICAgICAgIHJldHVybiBNYXBJbnQzMk1lc3NhZ2VEZWZhdWx0RW50cnlIb2xkZXIuZGVmYXVsdEVudHJ5OwogICAgICAgIH0KICAgICAgfTsKICAgICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgTWFwSW50MzJNZXNzYWdlQ29udmVydGVyIG1hcEludDMyTWVzc2FnZUNvbnZlcnRlciA9IG5ldyBNYXBJbnQzMk1lc3NhZ2VDb252ZXJ0ZXIoKTsKCiAgICAgIHByaXZhdGUgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8CiAgICAgICAgICBqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyPiBtYXBJbnQzMk1lc3NhZ2VfOwogICAgICBwcml2YXRlIGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXI+CiAgICAgICAgICBpbnRlcm5hbEdldE1hcEludDMyTWVzc2FnZSgpIHsKICAgICAgICBpZiAobWFwSW50MzJNZXNzYWdlXyA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuTWFwRmllbGRCdWlsZGVyPD4obWFwSW50MzJNZXNzYWdlQ29udmVydGVyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1hcEludDMyTWVzc2FnZV87CiAgICAgIH0KICAgICAgcHJpdmF0ZSBjb20uZ29vZ2xlLnByb3RvYnVmLk1hcEZpZWxkQnVpbGRlcjxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5CdWlsZGVyPgogICAgICAgICAgaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkgewogICAgICAgIGlmIChtYXBJbnQzMk1lc3NhZ2VfID09IG51bGwpIHsKICAgICAgICAgIG1hcEludDMyTWVzc2FnZV8gPSBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5NYXBGaWVsZEJ1aWxkZXI8PihtYXBJbnQzMk1lc3NhZ2VDb252ZXJ0ZXIpOwogICAgICAgIH0KICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIG1hcEludDMyTWVzc2FnZV87CiAgICAgIH0KICAgICAgcHVibGljIGludCBnZXRNYXBJbnQzMk1lc3NhZ2VDb3VudCgpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNYXBJbnQzMk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkuc2l6ZSgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWluc01hcEludDMyTWVzc2FnZSgKICAgICAgICAgIGludCBrZXkpIHsKCiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZW5zdXJlQnVpbGRlck1hcCgpLmNvbnRhaW5zS2V5KGtleSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSB7QGxpbmsgI2dldE1hcEludDMyTWVzc2FnZU1hcCgpfSBpbnN0ZWFkLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IGdldE1hcEludDMyTWVzc2FnZSgpIHsKICAgICAgICByZXR1cm4gZ2V0TWFwSW50MzJNZXNzYWdlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlPiBnZXRNYXBJbnQzMk1lc3NhZ2VNYXAoKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsR2V0TWFwSW50MzJNZXNzYWdlKCkuZ2V0SW1tdXRhYmxlTWFwKCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE1hcEludDMyTWVzc2FnZU9yRGVmYXVsdCgKICAgICAgICAgIGludCBrZXksCiAgICAgICAgICAvKiBudWxsYWJsZSAqLwpjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGRlZmF1bHRWYWx1ZSkgewoKICAgICAgICBqYXZhLnV0aWwuTWFwPGphdmEubGFuZy5JbnRlZ2VyLCBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlT3JCdWlsZGVyPiBtYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCk7CiAgICAgICAgcmV0dXJuIG1hcC5jb250YWluc0tleShrZXkpID8gbWFwSW50MzJNZXNzYWdlQ29udmVydGVyLmJ1aWxkKG1hcC5nZXQoa2V5KSkgOiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlIGdldE1hcEludDMyTWVzc2FnZU9yVGhyb3coCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IG1hcCA9IGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKTsKICAgICAgICBpZiAoIW1hcC5jb250YWluc0tleShrZXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLklsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFwSW50MzJNZXNzYWdlQ29udmVydGVyLmJ1aWxkKG1hcC5nZXQoa2V5KSk7CiAgICAgIH0KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJNYXBJbnQzMk1lc3NhZ2UoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyTWVzc2FnZSgpLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPm1hcCZsdDtpbnQzMiwgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0xpdGUmZ3Q7IG1hcF9pbnQzMl9tZXNzYWdlID0gMTs8L2NvZGU+CiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciByZW1vdmVNYXBJbnQzMk1lc3NhZ2UoCiAgICAgICAgICBpbnQga2V5KSB7CgogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucmVtb3ZlKGtleSk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZSBhbHRlcm5hdGUgbXV0YXRpb24gYWNjZXNzb3JzIGluc3RlYWQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQKICAgICAgcHVibGljIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+CiAgICAgICAgICBnZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkgewogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gaW50ZXJuYWxHZXRNdXRhYmxlTWFwSW50MzJNZXNzYWdlKCkuZW5zdXJlTWVzc2FnZU1hcCgpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5tYXAmbHQ7aW50MzIsIC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlJmd0OyBtYXBfaW50MzJfbWVzc2FnZSA9IDE7PC9jb2RlPgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgcHV0TWFwSW50MzJNZXNzYWdlKAogICAgICAgICAgaW50IGtleSwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUgdmFsdWUpIHsKCiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHsgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCJtYXAgdmFsdWUiKTsgfQogICAgICAgIGludGVybmFsR2V0TXV0YWJsZU1hcEludDMyTWVzc2FnZSgpLmVuc3VyZUJ1aWxkZXJNYXAoKQogICAgICAgICAgICAucHV0KGtleSwgdmFsdWUpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHB1dEFsbE1hcEludDMyTWVzc2FnZSgKICAgICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGU+IHZhbHVlcykgewogICAgICAgIGZvciAoamF2YS51dGlsLk1hcC5FbnRyeTxqYXZhLmxhbmcuSW50ZWdlciwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZT4gZSA6IHZhbHVlcy5lbnRyeVNldCgpKSB7CiAgICAgICAgICBpZiAoZS5nZXRLZXkoKSA9PSBudWxsIHx8IGUuZ2V0VmFsdWUoKSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCkKICAgICAgICAgICAgLnB1dEFsbCh2YWx1ZXMpOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+bWFwJmx0O2ludDMyLCAucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzTGl0ZSZndDsgbWFwX2ludDMyX21lc3NhZ2UgPSAxOzwvY29kZT4KICAgICAgICovCiAgICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5UZXN0QWxsVHlwZXNMaXRlLkJ1aWxkZXIgcHV0TWFwSW50MzJNZXNzYWdlQnVpbGRlcklmQWJzZW50KAogICAgICAgICAgaW50IGtleSkgewogICAgICAgIGphdmEudXRpbC5NYXA8amF2YS5sYW5nLkludGVnZXIsIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGVPckJ1aWxkZXI+IGJ1aWxkZXJNYXAgPSBpbnRlcm5hbEdldE11dGFibGVNYXBJbnQzMk1lc3NhZ2UoKS5lbnN1cmVCdWlsZGVyTWFwKCk7CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZU9yQnVpbGRlciBlbnRyeSA9IGJ1aWxkZXJNYXAuZ2V0KGtleSk7CiAgICAgICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgICAgIGVudHJ5ID0gY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZS5uZXdCdWlsZGVyKCk7CiAgICAgICAgICBidWlsZGVyTWFwLnB1dChrZXksIGVudHJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKGVudHJ5IGluc3RhbmNlb2YgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbFR5cGVzTGl0ZSkgewogICAgICAgICAgZW50cnkgPSAoKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUpIGVudHJ5KS50b0J1aWxkZXIoKTsKICAgICAgICAgIGJ1aWxkZXJNYXAucHV0KGtleSwgZW50cnkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gKGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLlRlc3RBbGxUeXBlc0xpdGUuQnVpbGRlcikgZW50cnk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUpCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdE1lc3NhZ2VNYXBMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0TWVzc2FnZU1hcExpdGUgZ2V0RGVmYXVsdEluc3RhbmNlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgICBAamF2YS5sYW5nLkRlcHJlY2F0ZWQgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0TWVzc2FnZU1hcExpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdE1lc3NhZ2VNYXBMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgVGVzdE1lc3NhZ2VNYXBMaXRlIHBhcnNlUGFydGlhbEZyb20oCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgICAgQnVpbGRlciBidWlsZGVyID0gbmV3QnVpbGRlcigpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBidWlsZGVyLm1lcmdlRnJvbShpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5VbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBlLmFzSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uKCkuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfSBjYXRjaCAoamF2YS5pby5JT0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oZSkKICAgICAgICAgICAgICAuc2V0VW5maW5pc2hlZE1lc3NhZ2UoYnVpbGRlci5idWlsZFBhcnRpYWwoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWlsZGVyLmJ1aWxkUGFydGlhbCgpOwogICAgICB9CiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgY29tLmdvb2dsZS5wcm90b2J1Zi5QYXJzZXI8VGVzdE1lc3NhZ2VNYXBMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RNZXNzYWdlTWFwTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRTsKICAgIH0KCiAgfQoKICBwdWJsaWMgaW50ZXJmYWNlIFRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3JCdWlsZGVyIHsKCiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGEgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIGJvb2xlYW4gaGFzQSgpOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBhID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBhLgogICAgICovCiAgICBpbnQgZ2V0QSgpOwoKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYiA9IDI7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBiIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgYm9vbGVhbiBoYXNCKCk7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGIgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGIuCiAgICAgKi8KICAgIGludCBnZXRCKCk7CgogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBjID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0MoKTsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYyA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYy4KICAgICAqLwogICAgaW50IGdldEMoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZX0KICAgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGNsYXNzIFRlc3RSZXF1aXJlZExpdGUgZXh0ZW5kcwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMyBpbXBsZW1lbnRzCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChtZXNzYWdlX2ltcGxlbWVudHM6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkKICAgICAgVGVzdFJlcXVpcmVkTGl0ZU9yQnVpbGRlciB7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgbG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMEw7CiAgICAvLyBVc2UgVGVzdFJlcXVpcmVkTGl0ZS5uZXdCdWlsZGVyKCkgdG8gY29uc3RydWN0LgogICAgcHJpdmF0ZSBUZXN0UmVxdWlyZWRMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgVGVzdFJlcXVpcmVkTGl0ZSgpIHsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBAU3VwcHJlc3NXYXJuaW5ncyh7InVudXNlZCJ9KQogICAgcHJvdGVjdGVkIGphdmEubGFuZy5PYmplY3QgbmV3SW5zdGFuY2UoCiAgICAgICAgVW51c2VkUHJpdmF0ZVBhcmFtZXRlciB1bnVzZWQpIHsKICAgICAgcmV0dXJuIG5ldyBUZXN0UmVxdWlyZWRMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UmVxdWlyZWRMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UmVxdWlyZWRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuY2xhc3MsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBBX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIGludCBhXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGEgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYSBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0EoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYSA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYS4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRBKCkgewogICAgICByZXR1cm4gYV87CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgQl9GSUVMRF9OVU1CRVIgPSAyOwogICAgcHJpdmF0ZSBpbnQgYl8gPSAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBiID0gMjs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGIgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBoYXNCKCkgewogICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCk7CiAgICB9CiAgICAvKioKICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGIgPSAyOzwvY29kZT4KICAgICAqIEByZXR1cm4gVGhlIGIuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgZ2V0QigpIHsKICAgICAgcmV0dXJuIGJfOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IENfRklFTERfTlVNQkVSID0gMzsKICAgIHByaXZhdGUgaW50IGNfID0gMDsKICAgIC8qKgogICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYyA9IDM7PC9jb2RlPgogICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBjIGZpZWxkIGlzIHNldC4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGJvb2xlYW4gaGFzQygpIHsKICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApOwogICAgfQogICAgLyoqCiAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBjID0gMzs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFRoZSBjLgogICAgICovCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldEMoKSB7CiAgICAgIHJldHVybiBjXzsKICAgIH0KCiAgICBwcml2YXRlIGJ5dGUgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gLTE7CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICBieXRlIGlzSW5pdGlhbGl6ZWQgPSBtZW1vaXplZElzSW5pdGlhbGl6ZWQ7CiAgICAgIGlmIChpc0luaXRpYWxpemVkID09IDEpIHJldHVybiB0cnVlOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAwKSByZXR1cm4gZmFsc2U7CgogICAgICBpZiAoIWhhc0EoKSkgewogICAgICAgIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IDA7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghaGFzQigpKSB7CiAgICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFoYXNDKCkpIHsKICAgICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAwOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBtZW1vaXplZElzSW5pdGlhbGl6ZWQgPSAxOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgdm9pZCB3cml0ZVRvKGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0gb3V0cHV0KQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIG91dHB1dC53cml0ZUludDMyKDEsIGFfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigyLCBiXyk7CiAgICAgIH0KICAgICAgaWYgKCgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApKSB7CiAgICAgICAgb3V0cHV0LndyaXRlSW50MzIoMywgY18pOwogICAgICB9CiAgICAgIGdldFVua25vd25GaWVsZHMoKS53cml0ZVRvKG91dHB1dCk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRTZXJpYWxpemVkU2l6ZSgpIHsKICAgICAgaW50IHNpemUgPSBtZW1vaXplZFNpemU7CiAgICAgIGlmIChzaXplICE9IC0xKSByZXR1cm4gc2l6ZTsKCiAgICAgIHNpemUgPSAwOwogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDEsIGFfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMikgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDIsIGJfKTsKICAgICAgfQogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICBzaXplICs9IGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRPdXRwdXRTdHJlYW0KICAgICAgICAgIC5jb21wdXRlSW50MzJTaXplKDMsIGNfKTsKICAgICAgfQogICAgICBzaXplICs9IGdldFVua25vd25GaWVsZHMoKS5nZXRTZXJpYWxpemVkU2l6ZSgpOwogICAgICBtZW1vaXplZFNpemUgPSBzaXplOwogICAgICByZXR1cm4gc2l6ZTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoZmluYWwgamF2YS5sYW5nLk9iamVjdCBvYmopIHsKICAgICAgaWYgKG9iaiA9PSB0aGlzKSB7CiAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgb3RoZXIgPSAocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUpIG9iajsKCiAgICAgIGlmIChoYXNBKCkgIT0gb3RoZXIuaGFzQSgpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNBKCkpIHsKICAgICAgICBpZiAoZ2V0QSgpCiAgICAgICAgICAgICE9IG90aGVyLmdldEEoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNCKCkgIT0gb3RoZXIuaGFzQigpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNCKCkpIHsKICAgICAgICBpZiAoZ2V0QigpCiAgICAgICAgICAgICE9IG90aGVyLmdldEIoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChoYXNDKCkgIT0gb3RoZXIuaGFzQygpKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmIChoYXNDKCkpIHsKICAgICAgICBpZiAoZ2V0QygpCiAgICAgICAgICAgICE9IG90aGVyLmdldEMoKSkgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghZ2V0VW5rbm93bkZpZWxkcygpLmVxdWFscyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBpbnQgaGFzaENvZGUoKSB7CiAgICAgIGlmIChtZW1vaXplZEhhc2hDb2RlICE9IDApIHsKICAgICAgICByZXR1cm4gbWVtb2l6ZWRIYXNoQ29kZTsKICAgICAgfQogICAgICBpbnQgaGFzaCA9IDQxOwogICAgICBoYXNoID0gKDE5ICogaGFzaCkgKyBnZXREZXNjcmlwdG9yKCkuaGFzaENvZGUoKTsKICAgICAgaWYgKGhhc0EoKSkgewogICAgICAgIGhhc2ggPSAoMzcgKiBoYXNoKSArIEFfRklFTERfTlVNQkVSOwogICAgICAgIGhhc2ggPSAoNTMgKiBoYXNoKSArIGdldEEoKTsKICAgICAgfQogICAgICBpZiAoaGFzQigpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgQl9GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0QigpOwogICAgICB9CiAgICAgIGlmIChoYXNDKCkpIHsKICAgICAgICBoYXNoID0gKDM3ICogaGFzaCkgKyBDX0ZJRUxEX05VTUJFUjsKICAgICAgICBoYXNoID0gKDUzICogaGFzaCkgKyBnZXRDKCk7CiAgICAgIH0KICAgICAgaGFzaCA9ICgyOSAqIGhhc2gpICsgZ2V0VW5rbm93bkZpZWxkcygpLmhhc2hDb2RlKCk7CiAgICAgIG1lbW9pemVkSGFzaENvZGUgPSBoYXNoOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBwYXJzZUZyb20oCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5CeXRlU3RyaW5nIGRhdGEpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkJ5dGVTdHJpbmcgZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcGFyc2VGcm9tKAogICAgICAgIGJ5dGVbXSBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcGFyc2VGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgpIHsgcmV0dXJuIG5ld0J1aWxkZXIoKTsgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBCdWlsZGVyIG5ld0J1aWxkZXIocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcHJvdG90eXBlKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFLnRvQnVpbGRlcigpLm1lcmdlRnJvbShwcm90b3R5cGUpOwogICAgfQogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgdG9CdWlsZGVyKCkgewogICAgICByZXR1cm4gdGhpcyA9PSBERUZBVUxUX0lOU1RBTkNFCiAgICAgICAgICA/IG5ldyBCdWlsZGVyKCkgOiBuZXcgQnVpbGRlcigpLm1lcmdlRnJvbSh0aGlzKTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwcm90ZWN0ZWQgQnVpbGRlciBuZXdCdWlsZGVyRm9yVHlwZSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyUGFyZW50IHBhcmVudCkgewogICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihwYXJlbnQpOwogICAgICByZXR1cm4gYnVpbGRlcjsKICAgIH0KICAgIC8qKgogICAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUpCiAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGVPckJ1aWxkZXIgewogICAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UmVxdWlyZWRMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgICAgLmVuc3VyZUZpZWxkQWNjZXNzb3JzSW5pdGlhbGl6ZWQoCiAgICAgICAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5jbGFzcywgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5uZXdCdWlsZGVyKCkKICAgICAgcHJpdmF0ZSBCdWlsZGVyKCkgewoKICAgICAgfQoKICAgICAgcHJpdmF0ZSBCdWlsZGVyKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuQnVpbGRlclBhcmVudCBwYXJlbnQpIHsKICAgICAgICBzdXBlcihwYXJlbnQpOwoKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyKCkgewogICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgYml0RmllbGQwXyA9IDA7CiAgICAgICAgYV8gPSAwOwogICAgICAgIGJfID0gMDsKICAgICAgICBjXyA9IDA7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgICAgZ2V0RGVzY3JpcHRvckZvclR5cGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2VGb3JUeXBlKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgYnVpbGQoKSB7CiAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcmVzdWx0ID0gYnVpbGRQYXJ0aWFsKCk7CiAgICAgICAgaWYgKCFyZXN1bHQuaXNJbml0aWFsaXplZCgpKSB7CiAgICAgICAgICB0aHJvdyBuZXdVbmluaXRpYWxpemVkTWVzc2FnZUV4Y2VwdGlvbihyZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBidWlsZFBhcnRpYWwoKSB7CiAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUgcmVzdWx0ID0gbmV3IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlKHRoaXMpOwogICAgICAgIGlmIChiaXRGaWVsZDBfICE9IDApIHsgYnVpbGRQYXJ0aWFsMChyZXN1bHQpOyB9CiAgICAgICAgb25CdWlsdCgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHByaXZhdGUgdm9pZCBidWlsZFBhcnRpYWwwKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIHJlc3VsdCkgewogICAgICAgIGludCBmcm9tX2JpdEZpZWxkMF8gPSBiaXRGaWVsZDBfOwogICAgICAgIGludCB0b19iaXRGaWVsZDBfID0gMDsKICAgICAgICBpZiAoKChmcm9tX2JpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgICAgcmVzdWx0LmFfID0gYV87CiAgICAgICAgICB0b19iaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgfQogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDIpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuYl8gPSBiXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMjsKICAgICAgICB9CiAgICAgICAgaWYgKCgoZnJvbV9iaXRGaWVsZDBfICYgMHgwMDAwMDAwNCkgIT0gMCkpIHsKICAgICAgICAgIHJlc3VsdC5jXyA9IGNfOwogICAgICAgICAgdG9fYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgIH0KICAgICAgICByZXN1bHQuYml0RmllbGQwXyB8PSB0b19iaXRGaWVsZDBfOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsb25lKCkgewogICAgICAgIHJldHVybiBzdXBlci5jbG9uZSgpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgc2V0RmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0RmllbGQoZmllbGQsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCkgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhckZpZWxkKGZpZWxkKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyT25lb2YoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLk9uZW9mRGVzY3JpcHRvciBvbmVvZikgewogICAgICAgIHJldHVybiBzdXBlci5jbGVhck9uZW9mKG9uZW9mKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGludCBpbmRleCwgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5zZXRSZXBlYXRlZEZpZWxkKGZpZWxkLCBpbmRleCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgYWRkUmVwZWF0ZWRGaWVsZCgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmllbGREZXNjcmlwdG9yIGZpZWxkLAogICAgICAgICAgamF2YS5sYW5nLk9iamVjdCB2YWx1ZSkgewogICAgICAgIHJldHVybiBzdXBlci5hZGRSZXBlYXRlZEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBtZXJnZUZyb20oY29tLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LlRlc3RSZXF1aXJlZExpdGUpIHsKICAgICAgICAgIHJldHVybiBtZXJnZUZyb20oKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIG90aGVyKSB7CiAgICAgICAgaWYgKG90aGVyID09IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKSByZXR1cm4gdGhpczsKICAgICAgICBpZiAob3RoZXIuaGFzQSgpKSB7CiAgICAgICAgICBzZXRBKG90aGVyLmdldEEoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChvdGhlci5oYXNCKCkpIHsKICAgICAgICAgIHNldEIob3RoZXIuZ2V0QigpKTsKICAgICAgICB9CiAgICAgICAgaWYgKG90aGVyLmhhc0MoKSkgewogICAgICAgICAgc2V0QyhvdGhlci5nZXRDKCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLm1lcmdlVW5rbm93bkZpZWxkcyhvdGhlci5nZXRVbmtub3duRmllbGRzKCkpOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBib29sZWFuIGlzSW5pdGlhbGl6ZWQoKSB7CiAgICAgICAgaWYgKCFoYXNBKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFoYXNCKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFoYXNDKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZElucHV0U3RyZWFtIGlucHV0LAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgICAgaWYgKGV4dGVuc2lvblJlZ2lzdHJ5ID09IG51bGwpIHsKICAgICAgICAgIHRocm93IG5ldyBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICAgICAgd2hpbGUgKCFkb25lKSB7CiAgICAgICAgICAgIGludCB0YWcgPSBpbnB1dC5yZWFkVGFnKCk7CiAgICAgICAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6IHsKICAgICAgICAgICAgICAgIGFfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgOAogICAgICAgICAgICAgIGNhc2UgMTY6IHsKICAgICAgICAgICAgICAgIGJfID0gaW5wdXQucmVhZEludDMyKCk7CiAgICAgICAgICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IC8vIGNhc2UgMTYKICAgICAgICAgICAgICBjYXNlIDI0OiB7CiAgICAgICAgICAgICAgICBjXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDA0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDI0CiAgICAgICAgICAgICAgZGVmYXVsdDogewogICAgICAgICAgICAgICAgaWYgKCFzdXBlci5wYXJzZVVua25vd25GaWVsZChpbnB1dCwgZXh0ZW5zaW9uUmVnaXN0cnksIHRhZykpIHsKICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7IC8vIHdhcyBhbiBlbmRncm91cCB0YWcKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0gLy8gZGVmYXVsdDoKICAgICAgICAgICAgfSAvLyBzd2l0Y2ggKHRhZykKICAgICAgICAgIH0gLy8gd2hpbGUgKCFkb25lKQogICAgICAgIH0gY2F0Y2ggKGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUudW53cmFwSU9FeGNlcHRpb24oKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgfSAvLyBmaW5hbGx5CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgcHJpdmF0ZSBpbnQgYml0RmllbGQwXzsKCiAgICAgIHByaXZhdGUgaW50IGFfIDsKICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGEgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBhIGZpZWxkIGlzIHNldC4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGJvb2xlYW4gaGFzQSgpIHsKICAgICAgICByZXR1cm4gKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGEgPSAxOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGUgYS4KICAgICAgICovCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGludCBnZXRBKCkgewogICAgICAgIHJldHVybiBhXzsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYSA9IDE7PC9jb2RlPgogICAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGEgdG8gc2V0LgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBzZXRBKGludCB2YWx1ZSkgewoKICAgICAgICBhXyA9IHZhbHVlOwogICAgICAgIGJpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYSA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoaXMgYnVpbGRlciBmb3IgY2hhaW5pbmcuCiAgICAgICAqLwogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckEoKSB7CiAgICAgICAgYml0RmllbGQwXyA9IChiaXRGaWVsZDBfICYgfjB4MDAwMDAwMDEpOwogICAgICAgIGFfID0gMDsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgcHJpdmF0ZSBpbnQgYl8gOwogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYiA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGIgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNCKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAyKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+cmVxdWlyZWQgaW50MzIgYiA9IDI7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBiLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEIoKSB7CiAgICAgICAgcmV0dXJuIGJfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBiID0gMjs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYiB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEIoaW50IHZhbHVlKSB7CgogICAgICAgIGJfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAyOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBiID0gMjs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQigpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMik7CiAgICAgICAgYl8gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBwcml2YXRlIGludCBjXyA7CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBjID0gMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYyBmaWVsZCBpcyBzZXQuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBib29sZWFuIGhhc0MoKSB7CiAgICAgICAgcmV0dXJuICgoYml0RmllbGQwXyAmIDB4MDAwMDAwMDQpICE9IDApOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5yZXF1aXJlZCBpbnQzMiBjID0gMzs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhlIGMuCiAgICAgICAqLwogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBpbnQgZ2V0QygpIHsKICAgICAgICByZXR1cm4gY187CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGMgPSAzOzwvY29kZT4KICAgICAgICogQHBhcmFtIHZhbHVlIFRoZSBjIHRvIHNldC4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgc2V0QyhpbnQgdmFsdWUpIHsKCiAgICAgICAgY18gPSB2YWx1ZTsKICAgICAgICBiaXRGaWVsZDBfIHw9IDB4MDAwMDAwMDQ7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIDxjb2RlPnJlcXVpcmVkIGludDMyIGMgPSAzOzwvY29kZT4KICAgICAgICogQHJldHVybiBUaGlzIGJ1aWxkZXIgZm9yIGNoYWluaW5nLgogICAgICAgKi8KICAgICAgcHVibGljIEJ1aWxkZXIgY2xlYXJDKCkgewogICAgICAgIGJpdEZpZWxkMF8gPSAoYml0RmllbGQwXyAmIH4weDAwMDAwMDA0KTsKICAgICAgICBjXyA9IDA7CiAgICAgICAgb25DaGFuZ2VkKCk7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBzZXRVbmtub3duRmllbGRzKAogICAgICAgICAgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbmtub3duRmllbGRTZXQgdW5rbm93bkZpZWxkcykgewogICAgICAgIHJldHVybiBzdXBlci5zZXRVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBmaW5hbCBCdWlsZGVyIG1lcmdlVW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIubWVyZ2VVbmtub3duRmllbGRzKHVua25vd25GaWVsZHMpOwogICAgICB9CgoKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KGJ1aWxkZXJfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkKICAgIH0KCiAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoY2xhc3Nfc2NvcGU6cHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIERFRkFVTFRfSU5TVEFOQ0U7CiAgICBzdGF0aWMgewogICAgICBERUZBVUxUX0lOU1RBTkNFID0gbmV3IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RSZXF1aXJlZExpdGU+CiAgICAgICAgUEFSU0VSID0gbmV3IGNvbS5nb29nbGUucHJvdG9idWYuQWJzdHJhY3RQYXJzZXI8VGVzdFJlcXVpcmVkTGl0ZT4oKSB7CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIFRlc3RSZXF1aXJlZExpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxUZXN0UmVxdWlyZWRMaXRlPiBwYXJzZXIoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPFRlc3RSZXF1aXJlZExpdGU+IGdldFBhcnNlckZvclR5cGUoKSB7CiAgICAgIHJldHVybiBQQVJTRVI7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgaW50IFNJTkdMRV9GSUVMRF9OVU1CRVIgPSAxMDAwOwogICAgLyoqCiAgICAgKiA8Y29kZT5leHRlbmQgLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zTGl0ZSB7IC4uLiB9PC9jb2RlPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZS5HZW5lcmF0ZWRFeHRlbnNpb248CiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5Vbml0dGVzdExpdGUuVGVzdEFsbEV4dGVuc2lvbnNMaXRlLAogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlPiBzaW5nbGUgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2UKICAgICAgICAgICAgLm5ld01lc3NhZ2VTY29wZWRHZW5lcmF0ZWRFeHRlbnNpb24oCiAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5nZXREZWZhdWx0SW5zdGFuY2UoKSwKICAgICAgICAgIDAsCiAgICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuVGVzdFJlcXVpcmVkTGl0ZS5jbGFzcywKICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpKTsKICB9CgogIHB1YmxpYyBpbnRlcmZhY2UgRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXIgZXh0ZW5kcwogICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoaW50ZXJmYWNlX2V4dGVuZHM6cHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUpCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9yQnVpbGRlciB7CgogICAgLyoqCiAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICovCiAgICBib29sZWFuIGhhc0MoKTsKICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYy4KICAgICAqLwogICAgaW50IGdldEMoKTsKICB9CiAgLyoqCiAgICogUHJvdG9idWYgdHlwZSB7QGNvZGUgcHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGV9CiAgICovCiAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBGb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBleHRlbmRzCiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzIGltcGxlbWVudHMKICAgICAgLy8gQEBwcm90b2NfaW5zZXJ0aW9uX3BvaW50KG1lc3NhZ2VfaW1wbGVtZW50czpwcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSkKICAgICAgRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVPckJ1aWxkZXIgewogIHByaXZhdGUgc3RhdGljIGZpbmFsIGxvbmcgc2VyaWFsVmVyc2lvblVJRCA9IDBMOwogICAgLy8gVXNlIEZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLm5ld0J1aWxkZXIoKSB0byBjb25zdHJ1Y3QuCiAgICBwcml2YXRlIEZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXI8Pz4gYnVpbGRlcikgewogICAgICBzdXBlcihidWlsZGVyKTsKICAgIH0KICAgIHByaXZhdGUgRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUoKSB7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgQFN1cHByZXNzV2FybmluZ3MoeyJ1bnVzZWQifSkKICAgIHByb3RlY3RlZCBqYXZhLmxhbmcuT2JqZWN0IG5ld0luc3RhbmNlKAogICAgICAgIFVudXNlZFByaXZhdGVQYXJhbWV0ZXIgdW51c2VkKSB7CiAgICAgIHJldHVybiBuZXcgRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgICAgIGdldERlc2NyaXB0b3IoKSB7CiAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlX2Rlc2NyaXB0b3I7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgIGludGVybmFsR2V0RmllbGRBY2Nlc3NvclRhYmxlKCkgewogICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUKICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZS5jbGFzcywgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLkJ1aWxkZXIuY2xhc3MpOwogICAgfQoKICAgIHByaXZhdGUgaW50IGJpdEZpZWxkMF87CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBDX0ZJRUxEX05VTUJFUiA9IDE7CiAgICBwcml2YXRlIGludCBjXyA9IDA7CiAgICAvKioKICAgICAqIDxjb2RlPm9wdGlvbmFsIGludDMyIGMgPSAxOzwvY29kZT4KICAgICAqIEByZXR1cm4gV2hldGhlciB0aGUgYyBmaWVsZCBpcyBzZXQuCiAgICAgKi8KICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGhhc0MoKSB7CiAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgIH0KICAgIC8qKgogICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICogQHJldHVybiBUaGUgYy4KICAgICAqLwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBnZXRDKCkgewogICAgICByZXR1cm4gY187CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIG1lbW9pemVkSXNJbml0aWFsaXplZCA9IC0xOwogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGZpbmFsIGJvb2xlYW4gaXNJbml0aWFsaXplZCgpIHsKICAgICAgYnl0ZSBpc0luaXRpYWxpemVkID0gbWVtb2l6ZWRJc0luaXRpYWxpemVkOwogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PSAxKSByZXR1cm4gdHJ1ZTsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT0gMCkgcmV0dXJuIGZhbHNlOwoKICAgICAgbWVtb2l6ZWRJc0luaXRpYWxpemVkID0gMTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIHZvaWQgd3JpdGVUbyhjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkT3V0cHV0U3RyZWFtIG91dHB1dCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICBpZiAoKChiaXRGaWVsZDBfICYgMHgwMDAwMDAwMSkgIT0gMCkpIHsKICAgICAgICBvdXRwdXQud3JpdGVJbnQzMigxLCBjXyk7CiAgICAgIH0KICAgICAgZ2V0VW5rbm93bkZpZWxkcygpLndyaXRlVG8ob3V0cHV0KTsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGdldFNlcmlhbGl6ZWRTaXplKCkgewogICAgICBpbnQgc2l6ZSA9IG1lbW9pemVkU2l6ZTsKICAgICAgaWYgKHNpemUgIT0gLTEpIHJldHVybiBzaXplOwoKICAgICAgc2l6ZSA9IDA7CiAgICAgIGlmICgoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKSkgewogICAgICAgIHNpemUgKz0gY29tLmdvb2dsZS5wcm90b2J1Zi5Db2RlZE91dHB1dFN0cmVhbQogICAgICAgICAgLmNvbXB1dGVJbnQzMlNpemUoMSwgY18pOwogICAgICB9CiAgICAgIHNpemUgKz0gZ2V0VW5rbm93bkZpZWxkcygpLmdldFNlcmlhbGl6ZWRTaXplKCk7CiAgICAgIG1lbW9pemVkU2l6ZSA9IHNpemU7CiAgICAgIHJldHVybiBzaXplOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhmaW5hbCBqYXZhLmxhbmcuT2JqZWN0IG9iaikgewogICAgICBpZiAob2JqID09IHRoaXMpIHsKICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSkpIHsKICAgICAgICByZXR1cm4gc3VwZXIuZXF1YWxzKG9iaik7CiAgICAgIH0KICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIG90aGVyID0gKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSkgb2JqOwoKICAgICAgaWYgKGhhc0MoKSAhPSBvdGhlci5oYXNDKCkpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGhhc0MoKSkgewogICAgICAgIGlmIChnZXRDKCkKICAgICAgICAgICAgIT0gb3RoZXIuZ2V0QygpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCFnZXRVbmtub3duRmllbGRzKCkuZXF1YWxzKG90aGVyLmdldFVua25vd25GaWVsZHMoKSkpIHJldHVybiBmYWxzZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIGludCBoYXNoQ29kZSgpIHsKICAgICAgaWYgKG1lbW9pemVkSGFzaENvZGUgIT0gMCkgewogICAgICAgIHJldHVybiBtZW1vaXplZEhhc2hDb2RlOwogICAgICB9CiAgICAgIGludCBoYXNoID0gNDE7CiAgICAgIGhhc2ggPSAoMTkgKiBoYXNoKSArIGdldERlc2NyaXB0b3IoKS5oYXNoQ29kZSgpOwogICAgICBpZiAoaGFzQygpKSB7CiAgICAgICAgaGFzaCA9ICgzNyAqIGhhc2gpICsgQ19GSUVMRF9OVU1CRVI7CiAgICAgICAgaGFzaCA9ICg1MyAqIGhhc2gpICsgZ2V0QygpOwogICAgICB9CiAgICAgIGhhc2ggPSAoMjkgKiBoYXNoKSArIGdldFVua25vd25GaWVsZHMoKS5oYXNoQ29kZSgpOwogICAgICBtZW1vaXplZEhhc2hDb2RlID0gaGFzaDsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEubmlvLkJ5dGVCdWZmZXIgZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBqYXZhLm5pby5CeXRlQnVmZmVyIGRhdGEsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgcmV0dXJuIFBBUlNFUi5wYXJzZUZyb20oZGF0YSwgZXh0ZW5zaW9uUmVnaXN0cnkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhKQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQnl0ZVN0cmluZyBkYXRhLAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgIHRocm93cyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBQQVJTRVIucGFyc2VGcm9tKGRhdGEsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIHBhcnNlRnJvbShieXRlW10gZGF0YSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBieXRlW10gZGF0YSwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gewogICAgICByZXR1cm4gUEFSU0VSLnBhcnNlRnJvbShkYXRhLCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZUZyb20oamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VGcm9tKAogICAgICAgIGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VEZWxpbWl0ZWRGcm9tKGphdmEuaW8uSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZURlbGltaXRlZFdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwYXJzZURlbGltaXRlZEZyb20oCiAgICAgICAgamF2YS5pby5JbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJlZ2lzdHJ5TGl0ZSBleHRlbnNpb25SZWdpc3RyeSkKICAgICAgICB0aHJvd3MgamF2YS5pby5JT0V4Y2VwdGlvbiB7CiAgICAgIHJldHVybiBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMwogICAgICAgICAgLnBhcnNlRGVsaW1pdGVkV2l0aElPRXhjZXB0aW9uKFBBUlNFUiwgaW5wdXQsIGV4dGVuc2lvblJlZ2lzdHJ5KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0KTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIHBhcnNlRnJvbSgKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkNvZGVkSW5wdXRTdHJlYW0gaW5wdXQsCiAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SZWdpc3RyeUxpdGUgZXh0ZW5zaW9uUmVnaXN0cnkpCiAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICByZXR1cm4gY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMKICAgICAgICAgIC5wYXJzZVdpdGhJT0V4Y2VwdGlvbihQQVJTRVIsIGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICB9CgogICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgcHVibGljIEJ1aWxkZXIgbmV3QnVpbGRlckZvclR5cGUoKSB7IHJldHVybiBuZXdCdWlsZGVyKCk7IH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKCkgewogICAgICByZXR1cm4gREVGQVVMVF9JTlNUQU5DRS50b0J1aWxkZXIoKTsKICAgIH0KICAgIHB1YmxpYyBzdGF0aWMgQnVpbGRlciBuZXdCdWlsZGVyKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBwcm90b3R5cGUpIHsKICAgICAgcmV0dXJuIERFRkFVTFRfSU5TVEFOQ0UudG9CdWlsZGVyKCkubWVyZ2VGcm9tKHByb3RvdHlwZSk7CiAgICB9CiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgQnVpbGRlciB0b0J1aWxkZXIoKSB7CiAgICAgIHJldHVybiB0aGlzID09IERFRkFVTFRfSU5TVEFOQ0UKICAgICAgICAgID8gbmV3IEJ1aWxkZXIoKSA6IG5ldyBCdWlsZGVyKCkubWVyZ2VGcm9tKHRoaXMpOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHByb3RlY3RlZCBCdWlsZGVyIG5ld0J1aWxkZXJGb3JUeXBlKAogICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgIEJ1aWxkZXIgYnVpbGRlciA9IG5ldyBCdWlsZGVyKHBhcmVudCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfQogICAgLyoqCiAgICAgKiBQcm90b2J1ZiB0eXBlIHtAY29kZSBwcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZX0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBjbGFzcyBCdWlsZGVyIGV4dGVuZHMKICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5CdWlsZGVyPEJ1aWxkZXI+IGltcGxlbWVudHMKICAgICAgICAvLyBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoYnVpbGRlcl9pbXBsZW1lbnRzOnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKQogICAgICAgIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZU9yQnVpbGRlciB7CiAgICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yKCkgewogICAgICAgIHJldHVybiBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X0ZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlX2Rlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHJvdGVjdGVkIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICAgICAgaW50ZXJuYWxHZXRGaWVsZEFjY2Vzc29yVGFibGUoKSB7CiAgICAgICAgcmV0dXJuIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5pbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlCiAgICAgICAgICAgIC5lbnN1cmVGaWVsZEFjY2Vzc29yc0luaXRpYWxpemVkKAogICAgICAgICAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLmNsYXNzLCBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuQnVpbGRlci5jbGFzcyk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCB1c2luZyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUubmV3QnVpbGRlcigpCiAgICAgIHByaXZhdGUgQnVpbGRlcigpIHsKCiAgICAgIH0KCiAgICAgIHByaXZhdGUgQnVpbGRlcigKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkJ1aWxkZXJQYXJlbnQgcGFyZW50KSB7CiAgICAgICAgc3VwZXIocGFyZW50KTsKCiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhcigpIHsKICAgICAgICBzdXBlci5jbGVhcigpOwogICAgICAgIGJpdEZpZWxkMF8gPSAwOwogICAgICAgIGNfID0gMDsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICAgICAgICBnZXREZXNjcmlwdG9yRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LmludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZV9kZXNjcmlwdG9yOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgZ2V0RGVmYXVsdEluc3RhbmNlRm9yVHlwZSgpIHsKICAgICAgICByZXR1cm4gcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlLmdldERlZmF1bHRJbnN0YW5jZSgpOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgYnVpbGQoKSB7CiAgICAgICAgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIHJlc3VsdCA9IGJ1aWxkUGFydGlhbCgpOwogICAgICAgIGlmICghcmVzdWx0LmlzSW5pdGlhbGl6ZWQoKSkgewogICAgICAgICAgdGhyb3cgbmV3VW5pbml0aWFsaXplZE1lc3NhZ2VFeGNlcHRpb24ocmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGJ1aWxkUGFydGlhbCgpIHsKICAgICAgICBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcmVzdWx0ID0gbmV3IHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSh0aGlzKTsKICAgICAgICBpZiAoYml0RmllbGQwXyAhPSAwKSB7IGJ1aWxkUGFydGlhbDAocmVzdWx0KTsgfQogICAgICAgIG9uQnVpbHQoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CgogICAgICBwcml2YXRlIHZvaWQgYnVpbGRQYXJ0aWFsMChwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcmVzdWx0KSB7CiAgICAgICAgaW50IGZyb21fYml0RmllbGQwXyA9IGJpdEZpZWxkMF87CiAgICAgICAgaW50IHRvX2JpdEZpZWxkMF8gPSAwOwogICAgICAgIGlmICgoKGZyb21fYml0RmllbGQwXyAmIDB4MDAwMDAwMDEpICE9IDApKSB7CiAgICAgICAgICByZXN1bHQuY18gPSBjXzsKICAgICAgICAgIHRvX2JpdEZpZWxkMF8gfD0gMHgwMDAwMDAwMTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmJpdEZpZWxkMF8gfD0gdG9fYml0RmllbGQwXzsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xvbmUoKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBqYXZhLmxhbmcuT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLnNldEZpZWxkKGZpZWxkLCB2YWx1ZSk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhckZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJGaWVsZChmaWVsZCk7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBjbGVhck9uZW9mKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5PbmVvZkRlc2NyaXB0b3Igb25lb2YpIHsKICAgICAgICByZXR1cm4gc3VwZXIuY2xlYXJPbmVvZihvbmVvZik7CiAgICAgIH0KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgQnVpbGRlciBzZXRSZXBlYXRlZEZpZWxkKAogICAgICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWVsZERlc2NyaXB0b3IgZmllbGQsCiAgICAgICAgICBpbnQgaW5kZXgsIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0UmVwZWF0ZWRGaWVsZChmaWVsZCwgaW5kZXgsIHZhbHVlKTsKICAgICAgfQogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIGFkZFJlcGVhdGVkRmllbGQoCiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpZWxkRGVzY3JpcHRvciBmaWVsZCwKICAgICAgICAgIGphdmEubGFuZy5PYmplY3QgdmFsdWUpIHsKICAgICAgICByZXR1cm4gc3VwZXIuYWRkUmVwZWF0ZWRGaWVsZChmaWVsZCwgdmFsdWUpOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKGNvbS5nb29nbGUucHJvdG9idWYuTWVzc2FnZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSkgewogICAgICAgICAgcmV0dXJuIG1lcmdlRnJvbSgocHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKW90aGVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VwZXIubWVyZ2VGcm9tKG90aGVyKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHVibGljIEJ1aWxkZXIgbWVyZ2VGcm9tKHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBvdGhlcikgewogICAgICAgIGlmIChvdGhlciA9PSBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUuZ2V0RGVmYXVsdEluc3RhbmNlKCkpIHJldHVybiB0aGlzOwogICAgICAgIGlmIChvdGhlci5oYXNDKCkpIHsKICAgICAgICAgIHNldEMob3RoZXIuZ2V0QygpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5tZXJnZVVua25vd25GaWVsZHMob3RoZXIuZ2V0VW5rbm93bkZpZWxkcygpKTsKICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgYm9vbGVhbiBpc0luaXRpYWxpemVkKCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICAgIHB1YmxpYyBCdWlsZGVyIG1lcmdlRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGphdmEuaW8uSU9FeGNlcHRpb24gewogICAgICAgIGlmIChleHRlbnNpb25SZWdpc3RyeSA9PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBib29sZWFuIGRvbmUgPSBmYWxzZTsKICAgICAgICAgIHdoaWxlICghZG9uZSkgewogICAgICAgICAgICBpbnQgdGFnID0gaW5wdXQucmVhZFRhZygpOwogICAgICAgICAgICBzd2l0Y2ggKHRhZykgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA4OiB7CiAgICAgICAgICAgICAgICBjXyA9IGlucHV0LnJlYWRJbnQzMigpOwogICAgICAgICAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBjYXNlIDgKICAgICAgICAgICAgICBkZWZhdWx0OiB7CiAgICAgICAgICAgICAgICBpZiAoIXN1cGVyLnBhcnNlVW5rbm93bkZpZWxkKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSwgdGFnKSkgewogICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTsgLy8gd2FzIGFuIGVuZGdyb3VwIHRhZwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfSAvLyBkZWZhdWx0OgogICAgICAgICAgICB9IC8vIHN3aXRjaCAodGFnKQogICAgICAgICAgfSAvLyB3aGlsZSAoIWRvbmUpCiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS51bndyYXBJT0V4Y2VwdGlvbigpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBvbkNoYW5nZWQoKTsKICAgICAgICB9IC8vIGZpbmFsbHkKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgICBwcml2YXRlIGludCBiaXRGaWVsZDBfOwoKICAgICAgcHJpdmF0ZSBpbnQgY18gOwogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhlIGMgZmllbGQgaXMgc2V0LgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgYm9vbGVhbiBoYXNDKCkgewogICAgICAgIHJldHVybiAoKGJpdEZpZWxkMF8gJiAweDAwMDAwMDAxKSAhPSAwKTsKICAgICAgfQogICAgICAvKioKICAgICAgICogPGNvZGU+b3B0aW9uYWwgaW50MzIgYyA9IDE7PC9jb2RlPgogICAgICAgKiBAcmV0dXJuIFRoZSBjLgogICAgICAgKi8KICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgaW50IGdldEMoKSB7CiAgICAgICAgcmV0dXJuIGNfOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgYyB0byBzZXQuCiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIHNldEMoaW50IHZhbHVlKSB7CgogICAgICAgIGNfID0gdmFsdWU7CiAgICAgICAgYml0RmllbGQwXyB8PSAweDAwMDAwMDAxOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIC8qKgogICAgICAgKiA8Y29kZT5vcHRpb25hbCBpbnQzMiBjID0gMTs8L2NvZGU+CiAgICAgICAqIEByZXR1cm4gVGhpcyBidWlsZGVyIGZvciBjaGFpbmluZy4KICAgICAgICovCiAgICAgIHB1YmxpYyBCdWlsZGVyIGNsZWFyQygpIHsKICAgICAgICBiaXRGaWVsZDBfID0gKGJpdEZpZWxkMF8gJiB+MHgwMDAwMDAwMSk7CiAgICAgICAgY18gPSAwOwogICAgICAgIG9uQ2hhbmdlZCgpOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgICAgcHVibGljIGZpbmFsIEJ1aWxkZXIgc2V0VW5rbm93bkZpZWxkcygKICAgICAgICAgIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuVW5rbm93bkZpZWxkU2V0IHVua25vd25GaWVsZHMpIHsKICAgICAgICByZXR1cm4gc3VwZXIuc2V0VW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgZmluYWwgQnVpbGRlciBtZXJnZVVua25vd25GaWVsZHMoCiAgICAgICAgICBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLlVua25vd25GaWVsZFNldCB1bmtub3duRmllbGRzKSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLm1lcmdlVW5rbm93bkZpZWxkcyh1bmtub3duRmllbGRzKTsKICAgICAgfQoKCiAgICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChidWlsZGVyX3Njb3BlOnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlKQogICAgfQoKICAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChjbGFzc19zY29wZTpwcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSkKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBERUZBVUxUX0lOU1RBTkNFOwogICAgc3RhdGljIHsKICAgICAgREVGQVVMVF9JTlNUQU5DRSA9IG5ldyBwcm90b2J1Zl91bml0dGVzdC5NYXBMaXRlVW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUoKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHByb3RvYnVmX3VuaXR0ZXN0Lk1hcExpdGVVbml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZSBnZXREZWZhdWx0SW5zdGFuY2UoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICAgIEBqYXZhLmxhbmcuRGVwcmVjYXRlZCBwdWJsaWMgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuUGFyc2VyPEZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPgogICAgICAgIFBBUlNFUiA9IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkFic3RyYWN0UGFyc2VyPEZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlPigpIHsKICAgICAgQGphdmEubGFuZy5PdmVycmlkZQogICAgICBwdWJsaWMgRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGUgcGFyc2VQYXJ0aWFsRnJvbSgKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuQ29kZWRJbnB1dFN0cmVhbSBpbnB1dCwKICAgICAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmVnaXN0cnlMaXRlIGV4dGVuc2lvblJlZ2lzdHJ5KQogICAgICAgICAgdGhyb3dzIGNvbS5nb29nbGUucHJvdG9idWYuSW52YWxpZFByb3RvY29sQnVmZmVyRXhjZXB0aW9uIHsKICAgICAgICBCdWlsZGVyIGJ1aWxkZXIgPSBuZXdCdWlsZGVyKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJ1aWxkZXIubWVyZ2VGcm9tKGlucHV0LCBleHRlbnNpb25SZWdpc3RyeSk7CiAgICAgICAgfSBjYXRjaCAoY29tLmdvb2dsZS5wcm90b2J1Zi5JbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24gZSkgewogICAgICAgICAgdGhyb3cgZS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChjb20uZ29vZ2xlLnByb3RvYnVmLlVuaW5pdGlhbGl6ZWRNZXNzYWdlRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IGUuYXNJbnZhbGlkUHJvdG9jb2xCdWZmZXJFeGNlcHRpb24oKS5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9IGNhdGNoIChqYXZhLmlvLklPRXhjZXB0aW9uIGUpIHsKICAgICAgICAgIHRocm93IG5ldyBjb20uZ29vZ2xlLnByb3RvYnVmLkludmFsaWRQcm90b2NvbEJ1ZmZlckV4Y2VwdGlvbihlKQogICAgICAgICAgICAgIC5zZXRVbmZpbmlzaGVkTWVzc2FnZShidWlsZGVyLmJ1aWxkUGFydGlhbCgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGRQYXJ0aWFsKCk7CiAgICAgIH0KICAgIH07CgogICAgcHVibGljIHN0YXRpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxGb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gcGFyc2VyKCkgewogICAgICByZXR1cm4gUEFSU0VSOwogICAgfQoKICAgIEBqYXZhLmxhbmcuT3ZlcnJpZGUKICAgIHB1YmxpYyBjb20uZ29vZ2xlLnByb3RvYnVmLlBhcnNlcjxGb3JlaWduTWVzc2FnZUFyZW5hTGl0ZT4gZ2V0UGFyc2VyRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuIFBBUlNFUjsKICAgIH0KCiAgICBAamF2YS5sYW5nLk92ZXJyaWRlCiAgICBwdWJsaWMgcHJvdG9idWZfdW5pdHRlc3QuTWFwTGl0ZVVuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlQXJlbmFMaXRlIGdldERlZmF1bHRJbnN0YW5jZUZvclR5cGUoKSB7CiAgICAgIHJldHVybiBERUZBVUxUX0lOU1RBTkNFOwogICAgfQoKICB9CgogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJJbnQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQ2NEludDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBVaW50MzJVaW50MzJFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBVaW50MzJVaW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQzMlNpbnQzMkVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQzMlNpbnQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTaW50NjRTaW50NjRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTaW50NjRTaW50NjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkNjRGaXhlZDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZsb2F0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRG91YmxlRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJEb3VibGVFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwQm9vbEJvb2xFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTdHJpbmdTdHJpbmdFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTdHJpbmdTdHJpbmdFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJCeXRlc0VudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJFbnVtRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJFbnVtRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX1RlYm9yaW5nRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfVGVib3JpbmdFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMySW50MzJFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMySW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQ2NEludDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQ2NEludDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBVaW50MzJVaW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBVaW50NjRVaW50NjRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFVpbnQ2NFVpbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNpbnQzMlNpbnQzMkVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDY0U2ludDY0RW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50NjRTaW50NjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ZpeGVkNjRTZml4ZWQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJEb3VibGVFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwQm9vbEJvb2xFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTdHJpbmdTdHJpbmdFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFN0cmluZ1N0cmluZ0VudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkVudW1FbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlX01hcEZpZWxkRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfTWFwRmllbGRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX0tub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfS25vd25NYXBGaWVsZEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX1Vua25vd25NYXBGaWVsZEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkRlc2NyaXB0b3IKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3I7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgCiAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUKICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9Lbm93bk1hcEZpZWxkRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9Vbmtub3duTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9NYXBJbnQzMk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIAogICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlCiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfTWFwSW50MzJNZXNzYWdlRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRGVzY3JpcHRvcgogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZExpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9maWVsZEFjY2Vzc29yVGFibGU7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5EZXNjcmlwdG9yCiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVfZGVzY3JpcHRvcjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCAKICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlOwoKICBwdWJsaWMgc3RhdGljIGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3IKICAgICAgZ2V0RGVzY3JpcHRvcigpIHsKICAgIHJldHVybiBkZXNjcmlwdG9yOwogIH0KICBwcml2YXRlIHN0YXRpYyAgY29tLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9ycy5GaWxlRGVzY3JpcHRvcgogICAgICBkZXNjcmlwdG9yOwogIHN0YXRpYyB7CiAgICBqYXZhLmxhbmcuU3RyaW5nW10gZGVzY3JpcHRvckRhdGEgPSB7CiAgICAgICJcblwnZ29vZ2xlL3Byb3RvYnVmL21hcF9saXRlX3VuaXR0ZXN0LnByb3QiICsKICAgICAgIm9cMDIyXDAyMXByb3RvYnVmX3VuaXR0ZXN0XDAzMiNnb29nbGUvcHJvdG9idWYvdW4iICsKICAgICAgIml0dGVzdF9saXRlLnByb3RvXCJcMzI3XDAyM1xuXDAxM1Rlc3RNYXBMaXRlXDAyMkpcblwwMTdtYXAiICsKICAgICAgIl9pbnQzMl9pbnQzMlwwMzBcMDAxIFwwMDMoXDAxMzIxLnByb3RvYnVmX3VuaXR0ZXN0LlQiICsKICAgICAgImVzdE1hcExpdGUuTWFwSW50MzJJbnQzMkVudHJ5XDAyMkpcblwwMTdtYXBfaW50IiArCiAgICAgICI2NF9pbnQ2NFwwMzBcMDAyIFwwMDMoXDAxMzIxLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNIiArCiAgICAgICJhcExpdGUuTWFwSW50NjRJbnQ2NEVudHJ5XDAyMk5cblwwMjFtYXBfdWludDMyXyIgKwogICAgICAidWludDMyXDAzMFwwMDMgXDAwMyhcMDEzMjMucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcCIgKwogICAgICAiTGl0ZS5NYXBVaW50MzJVaW50MzJFbnRyeVwwMjJOXG5cMDIxbWFwX3VpbnQ2NF8iICsKICAgICAgInVpbnQ2NFwwMzBcMDA0IFwwMDMoXDAxMzIzLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNYXAiICsKICAgICAgIkxpdGUuTWFwVWludDY0VWludDY0RW50cnlcMDIyTlxuXDAyMW1hcF9zaW50MzJfIiArCiAgICAgICJzaW50MzJcMDMwXDAwNSBcMDAzKFwwMTMyMy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwIiArCiAgICAgICJMaXRlLk1hcFNpbnQzMlNpbnQzMkVudHJ5XDAyMk5cblwwMjFtYXBfc2ludDY0XyIgKwogICAgICAic2ludDY0XDAzMFwwMDYgXDAwMyhcMDEzMjMucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcCIgKwogICAgICAiTGl0ZS5NYXBTaW50NjRTaW50NjRFbnRyeVwwMjJSXG5cMDIzbWFwX2ZpeGVkMzIiICsKICAgICAgIl9maXhlZDMyXDAzMFwwMDcgXDAwMyhcMDEzMjUucHJvdG9idWZfdW5pdHRlc3QuVGVzdE0iICsKICAgICAgImFwTGl0ZS5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5XDAyMlJcblwwMjNtYXBfZml4IiArCiAgICAgICJlZDY0X2ZpeGVkNjRcMDMwXDAxMCBcMDAzKFwwMTMyNS5wcm90b2J1Zl91bml0dGVzdC5UIiArCiAgICAgICJlc3RNYXBMaXRlLk1hcEZpeGVkNjRGaXhlZDY0RW50cnlcMDIyVlxuXDAyNW1hcCIgKwogICAgICAiX3NmaXhlZDMyX3NmaXhlZDMyXDAzMFx0IFwwMDMoXDAxMzI3LnByb3RvYnVmX3VuaXQiICsKICAgICAgInRlc3QuVGVzdE1hcExpdGUuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHIiICsKICAgICAgInlcMDIyVlxuXDAyNW1hcF9zZml4ZWQ2NF9zZml4ZWQ2NFwwMzBcbiBcMDAzKFwwMTMyNy5wcm90byIgKwogICAgICAiYnVmX3VuaXR0ZXN0LlRlc3RNYXBMaXRlLk1hcFNmaXhlZDY0U2ZpeCIgKwogICAgICAiZWQ2NEVudHJ5XDAyMkpcblwwMTdtYXBfaW50MzJfZmxvYXRcMDMwXDAxMyBcMDAzKFwwMTMyMS5wcm8iICsKICAgICAgInRvYnVmX3VuaXR0ZXN0LlRlc3RNYXBMaXRlLk1hcEludDMyRmxvYXQiICsKICAgICAgIkVudHJ5XDAyMkxcblwwMjBtYXBfaW50MzJfZG91YmxlXDAzMFwwMTQgXDAwMyhcMDEzMjIucHJvdG9iIiArCiAgICAgICJ1Zl91bml0dGVzdC5UZXN0TWFwTGl0ZS5NYXBJbnQzMkRvdWJsZUVuIiArCiAgICAgICJ0cnlcMDIyRlxuXHJtYXBfYm9vbF9ib29sXDAzMFxyIFwwMDMoXDAxMzIvLnByb3RvYnVmX3VuIiArCiAgICAgICJpdHRlc3QuVGVzdE1hcExpdGUuTWFwQm9vbEJvb2xFbnRyeVwwMjJOXG5cMDIxbSIgKwogICAgICAiYXBfc3RyaW5nX3N0cmluZ1wwMzBcMDE2IFwwMDMoXDAxMzIzLnByb3RvYnVmX3VuaXR0ZSIgKwogICAgICAic3QuVGVzdE1hcExpdGUuTWFwU3RyaW5nU3RyaW5nRW50cnlcMDIySlxuXDAxN20iICsKICAgICAgImFwX2ludDMyX2J5dGVzXDAzMFwwMTcgXDAwMyhcMDEzMjEucHJvdG9idWZfdW5pdHRlc3QiICsKICAgICAgIi5UZXN0TWFwTGl0ZS5NYXBJbnQzMkJ5dGVzRW50cnlcMDIySFxuXDAxNm1hcF9pIiArCiAgICAgICJudDMyX2VudW1cMDMwXDAyMCBcMDAzKFwwMTMyMC5wcm90b2J1Zl91bml0dGVzdC5UZXN0IiArCiAgICAgICJNYXBMaXRlLk1hcEludDMyRW51bUVudHJ5XDAyMl1cblwwMzFtYXBfaW50MzJfZiIgKwogICAgICAib3JlaWduX21lc3NhZ2VcMDMwXDAyMSBcMDAzKFwwMTMyOi5wcm90b2J1Zl91bml0dGVzdCIgKwogICAgICAiLlRlc3RNYXBMaXRlLk1hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeSIgKwogICAgICAiXDAyMj5cblwwMTB0ZWJvcmluZ1wwMzBcMDIyIFwwMDMoXDAxMzIsLnByb3RvYnVmX3VuaXR0ZXN0LlQiICsKICAgICAgImVzdE1hcExpdGUuVGVib3JpbmdFbnRyeVwwMzI0XG5cMDIyTWFwSW50MzJJbnQzIiArCiAgICAgICIyRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNVwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDA1OlwwMDI4XDAwMVwwMzI0IiArCiAgICAgICJcblwwMjJNYXBJbnQ2NEludDY0RW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwM1wwMjJcclxuXDAwNXZhbCIgKwogICAgICAidWVcMDMwXDAwMiBcMDAxKFwwMDM6XDAwMjhcMDAxXDAzMjZcblwwMjRNYXBVaW50MzJVaW50MzJFbnRyeVwwMjJcMDEzXG5cMDAzIiArCiAgICAgICJrZXlcMDMwXDAwMSBcMDAxKFxyXDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFxyOlwwMDI4XDAwMVwwMzI2XG5cMDI0TWFwVWludDYiICsKICAgICAgIjRVaW50NjRFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA0XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDQiICsKICAgICAgIjpcMDAyOFwwMDFcMDMyNlxuXDAyNE1hcFNpbnQzMlNpbnQzMkVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKCIgKwogICAgICAiXDAyMVwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDIxOlwwMDI4XDAwMVwwMzI2XG5cMDI0TWFwU2ludDY0U2ludDY0RSIgKwogICAgICAibnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDIyXDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMjI6XDAwMjhcMDAxXDAzMjhcblwwMjYiICsKICAgICAgIk1hcEZpeGVkMzJGaXhlZDMyRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwN1wwMjJcclxuXDAwNXYiICsKICAgICAgImFsdWVcMDMwXDAwMiBcMDAxKFwwMDc6XDAwMjhcMDAxXDAzMjhcblwwMjZNYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5IiArCiAgICAgICJcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNlwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDA2OlwwMDI4XDAwMVwwMzI6XG5cMDMwTWFwUyIgKwogICAgICAiZml4ZWQzMlNmaXhlZDMyRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAxN1wwMjJcclxuXDAwNXZhbCIgKwogICAgICAidWVcMDMwXDAwMiBcMDAxKFwwMTc6XDAwMjhcMDAxXDAzMjpcblwwMzBNYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkiICsKICAgICAgIlwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDIwXDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMjA6XDAwMjhcMDAxXDAzMjRcblwwMjJNYXBJIiArCiAgICAgICJudDMyRmxvYXRFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxIiArCiAgICAgICIoXDAwMjpcMDAyOFwwMDFcMDMyNVxuXDAyM01hcEludDMyRG91YmxlRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEiICsKICAgICAgIihcMDA1XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDE6XDAwMjhcMDAxXDAzMjJcblwwMjBNYXBCb29sQm9vbEVudHIiICsKICAgICAgInlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAxMFwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDEwOlwwMDI4XDAwMVwwMzI2XG5cMDI0TWFwIiArCiAgICAgICJTdHJpbmdTdHJpbmdFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcdFwwMjJcclxuXDAwNXZhbHVlXDAzMCIgKwogICAgICAiXDAwMiBcMDAxKFx0OlwwMDI4XDAwMVwwMzI0XG5cMDIyTWFwSW50MzJCeXRlc0VudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSIgKwogICAgICAiIFwwMDEoXDAwNVwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDE0OlwwMDI4XDAwMVwwMzJTXG5cMDIxTWFwSW50MzJFbnVtRSIgKwogICAgICAibnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMi1cblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAxNjJcMDM2LnByb3RvIiArCiAgICAgICJidWZfdW5pdHRlc3QuTWFwRW51bUxpdGU6XDAwMjhcMDAxXDAzMmRcblwwMzNNYXBJbnQzMiIgKwogICAgICAiRm9yZWlnbk1lc3NhZ2VFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMjRcblwwMDV2YWx1IiArCiAgICAgICJlXDAzMFwwMDIgXDAwMShcMDEzMiUucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhIiArCiAgICAgICJnZUxpdGU6XDAwMjhcMDAxXDAzMi9cblxyVGVib3JpbmdFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1IiArCiAgICAgICJcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAwNTpcMDAyOFwwMDFcIlwzMDVcMDIzXG5cMDIwVGVzdEFyZW5hTWFwTGl0ZSIgKwogICAgICAiXDAyMk9cblwwMTdtYXBfaW50MzJfaW50MzJcMDMwXDAwMSBcMDAzKFwwMTMyNi5wcm90b2J1Zl91bmkiICsKICAgICAgInR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwSW50MzJJbnQzMkVudHIiICsKICAgICAgInlcMDIyT1xuXDAxN21hcF9pbnQ2NF9pbnQ2NFwwMzBcMDAyIFwwMDMoXDAxMzI2LnByb3RvYnVmX3VuIiArCiAgICAgICJpdHRlc3QuVGVzdEFyZW5hTWFwTGl0ZS5NYXBJbnQ2NEludDY0RW50IiArCiAgICAgICJyeVwwMjJTXG5cMDIxbWFwX3VpbnQzMl91aW50MzJcMDMwXDAwMyBcMDAzKFwwMTMyOC5wcm90b2J1ZiIgKwogICAgICAiX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwVWludDMyVWludCIgKwogICAgICAiMzJFbnRyeVwwMjJTXG5cMDIxbWFwX3VpbnQ2NF91aW50NjRcMDMwXDAwNCBcMDAzKFwwMTMyOC5wcm8iICsKICAgICAgInRvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwVWludDYiICsKICAgICAgIjRVaW50NjRFbnRyeVwwMjJTXG5cMDIxbWFwX3NpbnQzMl9zaW50MzJcMDMwXDAwNSBcMDAzKFwwMTMyIiArCiAgICAgICI4LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwIiArCiAgICAgICJTaW50MzJTaW50MzJFbnRyeVwwMjJTXG5cMDIxbWFwX3NpbnQ2NF9zaW50NjRcMDMwXDAwNiIgKwogICAgICAiIFwwMDMoXDAxMzI4LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdCIgKwogICAgICAiZS5NYXBTaW50NjRTaW50NjRFbnRyeVwwMjJXXG5cMDIzbWFwX2ZpeGVkMzJfZmkiICsKICAgICAgInhlZDMyXDAzMFwwMDcgXDAwMyhcMDEzMjoucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW4iICsKICAgICAgImFNYXBMaXRlLk1hcEZpeGVkMzJGaXhlZDMyRW50cnlcMDIyV1xuXDAyM21hcF9mIiArCiAgICAgICJpeGVkNjRfZml4ZWQ2NFwwMzBcMDEwIFwwMDMoXDAxMzI6LnByb3RvYnVmX3VuaXR0ZXN0IiArCiAgICAgICIuVGVzdEFyZW5hTWFwTGl0ZS5NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5IiArCiAgICAgICJcMDIyW1xuXDAyNW1hcF9zZml4ZWQzMl9zZml4ZWQzMlwwMzBcdCBcMDAzKFwwMTMyPC5wcm90b2IiICsKICAgICAgInVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdGUuTWFwU2ZpeGVkMzIiICsKICAgICAgIlNmaXhlZDMyRW50cnlcMDIyW1xuXDAyNW1hcF9zZml4ZWQ2NF9zZml4ZWQ2NFwwMzBcbiIgKwogICAgICAiIFwwMDMoXDAxMzI8LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1hcExpdCIgKwogICAgICAiZS5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlcMDIyT1xuXDAxN21hcF9pbnQzMl8iICsKICAgICAgImZsb2F0XDAzMFwwMTMgXDAwMyhcMDEzMjYucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW4iICsKICAgICAgImFNYXBMaXRlLk1hcEludDMyRmxvYXRFbnRyeVwwMjJRXG5cMDIwbWFwX2ludDMyIiArCiAgICAgICJfZG91YmxlXDAzMFwwMTQgXDAwMyhcMDEzMjcucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyIiArCiAgICAgICJlbmFNYXBMaXRlLk1hcEludDMyRG91YmxlRW50cnlcMDIyS1xuXHJtYXBfYm8iICsKICAgICAgIm9sX2Jvb2xcMDMwXHIgXDAwMyhcMDEzMjQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyIiArCiAgICAgICJlbmFNYXBMaXRlLk1hcEJvb2xCb29sRW50cnlcMDIyU1xuXDAyMW1hcF9zdHJpbiIgKwogICAgICAiZ19zdHJpbmdcMDMwXDAxNiBcMDAzKFwwMTMyOC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QSIgKwogICAgICAicmVuYU1hcExpdGUuTWFwU3RyaW5nU3RyaW5nRW50cnlcMDIyT1xuXDAxN21hcF8iICsKICAgICAgImludDMyX2J5dGVzXDAzMFwwMTcgXDAwMyhcMDEzMjYucHJvdG9idWZfdW5pdHRlc3QuVGUiICsKICAgICAgInN0QXJlbmFNYXBMaXRlLk1hcEludDMyQnl0ZXNFbnRyeVwwMjJNXG5cMDE2bWFwIiArCiAgICAgICJfaW50MzJfZW51bVwwMzBcMDIwIFwwMDMoXDAxMzI1LnByb3RvYnVmX3VuaXR0ZXN0LlRlIiArCiAgICAgICJzdEFyZW5hTWFwTGl0ZS5NYXBJbnQzMkVudW1FbnRyeVwwMjJiXG5cMDMxbWFwXyIgKwogICAgICAiaW50MzJfZm9yZWlnbl9tZXNzYWdlXDAzMFwwMjEgXDAwMyhcMDEzMj8ucHJvdG9idWZfdSIgKwogICAgICAibml0dGVzdC5UZXN0QXJlbmFNYXBMaXRlLk1hcEludDMyRm9yZWlnbiIgKwogICAgICAiTWVzc2FnZUVudHJ5XDAzMjRcblwwMjJNYXBJbnQzMkludDMyRW50cnlcMDIyXDAxM1xuXDAwM2tlIiArCiAgICAgICJ5XDAzMFwwMDEgXDAwMShcMDA1XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDU6XDAwMjhcMDAxXDAzMjRcblwwMjJNYXBJbnQ2NEluIiArCiAgICAgICJ0NjRFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDAzXDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDM6XDAwMjhcMDAxIiArCiAgICAgICJcMDMyNlxuXDAyNE1hcFVpbnQzMlVpbnQzMkVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFxyXDAyMlxyXG4iICsKICAgICAgIlwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXHI6XDAwMjhcMDAxXDAzMjZcblwwMjRNYXBVaW50NjRVaW50NjRFbnRyeSIgKwogICAgICAiXDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDRcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAwNDpcMDAyOFwwMDFcMDMyNlxuXDAyNE1hcFMiICsKICAgICAgImludDMyU2ludDMyRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAyMVwwMjJcclxuXDAwNXZhbHVlXDAzMFwwMDIiICsKICAgICAgIiBcMDAxKFwwMjE6XDAwMjhcMDAxXDAzMjZcblwwMjRNYXBTaW50NjRTaW50NjRFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMCIgKwogICAgICAiXDAwMSBcMDAxKFwwMjJcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAyMjpcMDAyOFwwMDFcMDMyOFxuXDAyNk1hcEZpeGVkMzJGaSIgKwogICAgICAieGVkMzJFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA3XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDc6XDAwMiIgKwogICAgICAiOFwwMDFcMDMyOFxuXDAyNk1hcEZpeGVkNjRGaXhlZDY0RW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoIiArCiAgICAgICJcMDA2XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMDY6XDAwMjhcMDAxXDAzMjpcblwwMzBNYXBTZml4ZWQzMlNmaXhlIiArCiAgICAgICJkMzJFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDE3XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMTc6XDAwMjhcMDAxIiArCiAgICAgICJcMDMyOlxuXDAzME1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMSgiICsKICAgICAgIlwwMjBcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAyMDpcMDAyOFwwMDFcMDMyNFxuXDAyMk1hcEludDMyRmxvYXRFbnQiICsKICAgICAgInJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyXHJcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAwMjpcMDAyOFwwMDFcMDMyNVxuXDAyM01hIiArCiAgICAgICJwSW50MzJEb3VibGVFbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMlxyXG5cMDA1dmFsdWVcMDMwIiArCiAgICAgICJcMDAyIFwwMDEoXDAwMTpcMDAyOFwwMDFcMDMyMlxuXDAyME1hcEJvb2xCb29sRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEiICsKICAgICAgIihcMDEwXDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMTA6XDAwMjhcMDAxXDAzMjZcblwwMjRNYXBTdHJpbmdTdHJpbmciICsKICAgICAgIkVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFx0XDAyMlxyXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFx0OlwwMDI4XDAwMVwwMzI0XG4iICsKICAgICAgIlwwMjJNYXBJbnQzMkJ5dGVzRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNVwwMjJcclxuXDAwNXZhbHUiICsKICAgICAgImVcMDMwXDAwMiBcMDAxKFwwMTQ6XDAwMjhcMDAxXDAzMlNcblwwMjFNYXBJbnQzMkVudW1FbnRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMCIgKwogICAgICAiXDAwMSBcMDAxKFwwMDVcMDIyLVxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDE2MlwwMzYucHJvdG9idWZfdW5pdHRlc3QiICsKICAgICAgIi5NYXBFbnVtTGl0ZTpcMDAyOFwwMDFcMDMyaVxuXDAzM01hcEludDMyRm9yZWlnbk1lc3NhIiArCiAgICAgICJnZUVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyOVxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDEzMioucHIiICsKICAgICAgIm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZUFyZW5hTGl0ZToiICsKICAgICAgIlwwMDI4XDAwMVwiXDMwMlwwMDFcblwwMzJUZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZVwwMjJOXG5cdG1hIiArCiAgICAgICJwX2ZpZWxkXDAzMFwwMDEgXDAwMyhcMDEzMjsucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlIiArCiAgICAgICJxdWlyZWRNZXNzYWdlTWFwTGl0ZS5NYXBGaWVsZEVudHJ5XDAzMlRcblxyTWEiICsKICAgICAgInBGaWVsZEVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyMlxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDEzMiIgKwogICAgICAiIy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRMaXRlOlwwMDI4XDAwMSIgKwogICAgICAiXCJcMzU3XDAwMlxuXDAxN1Rlc3RFbnVtTWFwTGl0ZVwwMjJOXG5cMDE3a25vd25fbWFwX2ZpZWxkXDAzMCIgKwogICAgICAiZSBcMDAzKFwwMTMyNS5wcm90b2J1Zl91bml0dGVzdC5UZXN0RW51bU1hcExpdCIgKwogICAgICAiZS5Lbm93bk1hcEZpZWxkRW50cnlcMDIyUlxuXDAyMXVua25vd25fbWFwX2ZpZWwiICsKICAgICAgImRcMDMwZiBcMDAzKFwwMTMyNy5wcm90b2J1Zl91bml0dGVzdC5UZXN0RW51bU1hcEwiICsKICAgICAgIml0ZS5Vbmtub3duTWFwRmllbGRFbnRyeVwwMzJaXG5cMDIyS25vd25NYXBGaWVsIiArCiAgICAgICJkRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNVwwMjIzXG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMTYyJC5wcm8iICsKICAgICAgInRvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVudW1MaXRlOlwwMDI4XDAwMVwwMzJcXFxuXDAyNCIgKwogICAgICAiVW5rbm93bk1hcEZpZWxkRW50cnlcMDIyXDAxM1xuXDAwM2tleVwwMzBcMDAxIFwwMDEoXDAwNVwwMjIzXG5cMDA1dmFsIiArCiAgICAgICJ1ZVwwMzBcMDAyIFwwMDEoXDAxNjIkLnByb3RvYnVmX3VuaXR0ZXN0LlByb3RvMk1hcEVuIiArCiAgICAgICJ1bUxpdGU6XDAwMjhcMDAxXCJcMjM0XDAwM1xuXDAzMFRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZVwwMjIiICsKICAgICAgIldcblwwMTdrbm93bl9tYXBfZmllbGRcMDMwZSBcMDAzKFwwMTMyPi5wcm90b2J1Zl91bml0IiArCiAgICAgICJ0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZS5Lbm93bk1hcEZpIiArCiAgICAgICJlbGRFbnRyeVwwMjJbXG5cMDIxdW5rbm93bl9tYXBfZmllbGRcMDMwZiBcMDAzKFwwMTMyQC5wciIgKwogICAgICAib3RvYnVmX3VuaXR0ZXN0LlRlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZSIgKwogICAgICAiLlVua25vd25NYXBGaWVsZEVudHJ5XDAzMmNcblwwMjJLbm93bk1hcEZpZWxkRW4iICsKICAgICAgInRyeVwwMjJcMDEzXG5cMDAza2V5XDAzMFwwMDEgXDAwMShcMDA1XDAyMjxcblwwMDV2YWx1ZVwwMzBcMDAyIFwwMDEoXDAxNjItLnByb3RvYiIgKwogICAgICAidWZfdW5pdHRlc3QuUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGU6XDAwMiIgKwogICAgICAiOFwwMDFcMDMyZVxuXDAyNFVua25vd25NYXBGaWVsZEVudHJ5XDAyMlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyIiArCiAgICAgICI8XG5cMDA1dmFsdWVcMDMwXDAwMiBcMDAxKFwwMTYyLS5wcm90b2J1Zl91bml0dGVzdC5Qcm90byIgKwogICAgICAiMk1hcEVudW1QbHVzRXh0cmFMaXRlOlwwMDI4XDAwMVwiXDMxMFwwMDFcblwwMjJUZXN0TWVzc2FnIiArCiAgICAgICJlTWFwTGl0ZVwwMjJVXG5cMDIxbWFwX2ludDMyX21lc3NhZ2VcMDMwXDAwMSBcMDAzKFwwMTMyOi5wciIgKwogICAgICAib3RvYnVmX3VuaXR0ZXN0LlRlc3RNZXNzYWdlTWFwTGl0ZS5NYXBJbiIgKwogICAgICAidDMyTWVzc2FnZUVudHJ5XDAzMltcblwwMjRNYXBJbnQzMk1lc3NhZ2VFbnRyeVwwMjIiICsKICAgICAgIlwwMTNcblwwMDNrZXlcMDMwXDAwMSBcMDAxKFwwMDVcMDIyMlxuXDAwNXZhbHVlXDAzMFwwMDIgXDAwMShcMDEzMiMucHJvdG9idWZfdSIgKwogICAgICAibml0dGVzdC5UZXN0QWxsVHlwZXNMaXRlOlwwMDI4XDAwMVwiXDIyM1wwMDFcblwwMjBUZXN0UmVxIiArCiAgICAgICJ1aXJlZExpdGVcMDIyXHRcblwwMDFhXDAzMFwwMDEgXDAwMihcMDA1XDAyMlx0XG5cMDAxYlwwMzBcMDAyIFwwMDIoXDAwNVwwMjJcdFxuXDAwMWNcMDMwXDAwMyBcMDAyIiArCiAgICAgICIoXDAwNTJeXG5cMDA2c2luZ2xlXDAyMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbCIgKwogICAgICAiRXh0ZW5zaW9uc0xpdGVcMDMwXDM1MFwwMDcgXDAwMShcMDEzMiMucHJvdG9idWZfdW5pdHRlcyIgKwogICAgICAidC5UZXN0UmVxdWlyZWRMaXRlXCIkXG5cMDI3Rm9yZWlnbk1lc3NhZ2VBcmVuIiArCiAgICAgICJhTGl0ZVwwMjJcdFxuXDAwMWNcMDMwXDAwMSBcMDAxKFwwMDUqbVxuXDAyMVByb3RvMk1hcEVudW1MaXRlXDAyMlwwMzRcbiIgKwogICAgICAiXDAzMFBST1RPMl9NQVBfRU5VTV9GT09fTElURVwwMjBcMDAwXDAyMlwwMzRcblwwMzBQUk9UTzJfTUEiICsKICAgICAgIlBfRU5VTV9CQVJfTElURVwwMjBcMDAxXDAyMlwwMzRcblwwMzBQUk9UTzJfTUFQX0VOVU1fQkFaIiArCiAgICAgICJfTElURVwwMjBcMDAyKlwyMzZcMDAxXG5cMDMyUHJvdG8yTWFwRW51bVBsdXNFeHRyYUxpdGVcMDIyXDAzNiIgKwogICAgICAiXG5cMDMyRV9QUk9UTzJfTUFQX0VOVU1fRk9PX0xJVEVcMDIwXDAwMFwwMjJcMDM2XG5cMDMyRV9QUk9UIiArCiAgICAgICJPMl9NQVBfRU5VTV9CQVJfTElURVwwMjBcMDAxXDAyMlwwMzZcblwwMzJFX1BST1RPMl9NQVBfRSIgKwogICAgICAiTlVNX0JBWl9MSVRFXDAyMFwwMDJcMDIyIFxuXDAzNEVfUFJPVE8yX01BUF9FTlVNX0VYVFIiICsKICAgICAgIkFfTElURVwwMjBcMDAzKlJcblwwMTNNYXBFbnVtTGl0ZVwwMjJcMDI1XG5cMDIxTUFQX0VOVU1fRk9PXyIgKwogICAgICAiTElURVwwMjBcMDAwXDAyMlwwMjVcblwwMjFNQVBfRU5VTV9CQVJfTElURVwwMjBcMDAxXDAyMlwwMjVcblwwMjFNQVBfRU5VIiArCiAgICAgICJNX0JBWl9MSVRFXDAyMFwwMDJCXDAwNUhcMDAzXDM3MFwwMDFcMDAxIgogICAgfTsKICAgIGRlc2NyaXB0b3IgPSBjb20uZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JzLkZpbGVEZXNjcmlwdG9yCiAgICAgIC5pbnRlcm5hbEJ1aWxkR2VuZXJhdGVkRmlsZUZyb20oZGVzY3JpcHRvckRhdGEsCiAgICAgICAgbmV3IGNvbS5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvcnMuRmlsZURlc2NyaXB0b3JbXSB7CiAgICAgICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLlVuaXR0ZXN0TGl0ZS5nZXREZXNjcmlwdG9yKCksCiAgICAgICAgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIk1hcEludDMySW50MzIiLCAiTWFwSW50NjRJbnQ2NCIsICJNYXBVaW50MzJVaW50MzIiLCAiTWFwVWludDY0VWludDY0IiwgIk1hcFNpbnQzMlNpbnQzMiIsICJNYXBTaW50NjRTaW50NjQiLCAiTWFwRml4ZWQzMkZpeGVkMzIiLCAiTWFwRml4ZWQ2NEZpeGVkNjQiLCAiTWFwU2ZpeGVkMzJTZml4ZWQzMiIsICJNYXBTZml4ZWQ2NFNmaXhlZDY0IiwgIk1hcEludDMyRmxvYXQiLCAiTWFwSW50MzJEb3VibGUiLCAiTWFwQm9vbEJvb2wiLCAiTWFwU3RyaW5nU3RyaW5nIiwgIk1hcEludDMyQnl0ZXMiLCAiTWFwSW50MzJFbnVtIiwgIk1hcEludDMyRm9yZWlnbk1lc3NhZ2UiLCAiVGVib3JpbmciLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMySW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDY0SW50NjRFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDIpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFVpbnQzMlVpbnQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFVpbnQzMlVpbnQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBVaW50NjRVaW50NjRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQzMlNpbnQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg0KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTaW50MzJTaW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTaW50MzJTaW50MzJFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ludDY0U2ludDY0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDUpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQ2NFNpbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNpbnQ2NFNpbnQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg2KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkMzJGaXhlZDMyRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkNjRGaXhlZDY0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDcpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEZpeGVkNjRGaXhlZDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg4KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDkpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTApOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZsb2F0RW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRG91YmxlRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDExKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRG91YmxlRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEJvb2xCb29sRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDEyKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBCb29sQm9vbEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEJvb2xCb29sRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcFN0cmluZ1N0cmluZ0VudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxMyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTQpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyQnl0ZXNFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkJ5dGVzRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxNSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJFbnVtRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1hcExpdGVfTWFwSW50MzJFbnVtRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTYpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX1RlYm9yaW5nRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDE3KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWFwTGl0ZV9UZWJvcmluZ0VudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNYXBMaXRlX1RlYm9yaW5nRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJNYXBJbnQzMkludDMyIiwgIk1hcEludDY0SW50NjQiLCAiTWFwVWludDMyVWludDMyIiwgIk1hcFVpbnQ2NFVpbnQ2NCIsICJNYXBTaW50MzJTaW50MzIiLCAiTWFwU2ludDY0U2ludDY0IiwgIk1hcEZpeGVkMzJGaXhlZDMyIiwgIk1hcEZpeGVkNjRGaXhlZDY0IiwgIk1hcFNmaXhlZDMyU2ZpeGVkMzIiLCAiTWFwU2ZpeGVkNjRTZml4ZWQ2NCIsICJNYXBJbnQzMkZsb2F0IiwgIk1hcEludDMyRG91YmxlIiwgIk1hcEJvb2xCb29sIiwgIk1hcFN0cmluZ1N0cmluZyIsICJNYXBJbnQzMkJ5dGVzIiwgIk1hcEludDMyRW51bSIsICJNYXBJbnQzMkZvcmVpZ25NZXNzYWdlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkludDMyRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDEpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50NjRJbnQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFVpbnQzMlVpbnQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDIpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwVWludDMyVWludDMyRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBVaW50MzJVaW50MzJFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBVaW50NjRVaW50NjRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgzKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFVpbnQ2NFVpbnQ2NEVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwVWludDY0VWludDY0RW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDMyU2ludDMyRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoNCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50MzJTaW50MzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNpbnQzMlNpbnQzMkVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNpbnQ2NFNpbnQ2NEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDUpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU2ludDY0U2ludDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTaW50NjRTaW50NjRFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDMyRml4ZWQzMkVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDYpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQzMkZpeGVkMzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEZpeGVkMzJGaXhlZDMyRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg3KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEZpeGVkNjRGaXhlZDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBGaXhlZDY0Rml4ZWQ2NEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCg4KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoOSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJGbG9hdEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDEwKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRmxvYXRFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDExKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRG91YmxlRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkRvdWJsZUVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEJvb2xCb29sRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTIpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwQm9vbEJvb2xFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEJvb2xCb29sRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTMpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwU3RyaW5nU3RyaW5nRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBTdHJpbmdTdHJpbmdFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9NYXBJbnQzMkJ5dGVzRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMTQpOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJCeXRlc0VudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJCeXRlc0VudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDE1KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRW51bUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJFbnVtRW50cnlfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIktleSIsICJWYWx1ZSIsIH0pOwogICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RBcmVuYU1hcExpdGVfTWFwSW50MzJGb3JlaWduTWVzc2FnZUVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEFyZW5hTWFwTGl0ZV9kZXNjcmlwdG9yLmdldE5lc3RlZFR5cGVzKCkuZ2V0KDE2KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0QXJlbmFNYXBMaXRlX01hcEludDMyRm9yZWlnbk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMik7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIk1hcEZpZWxkIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfTWFwRmllbGRFbnRyeV9kZXNjcmlwdG9yID0KICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZE1lc3NhZ2VNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTWVzc2FnZU1hcExpdGVfTWFwRmllbGRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UmVxdWlyZWRNZXNzYWdlTWFwTGl0ZV9NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoMyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS25vd25NYXBGaWVsZCIsICJVbmtub3duTWFwRmllbGQiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX0tub3duTWFwRmllbGRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcExpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBMaXRlX1Vua25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoNCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RFbnVtTWFwUGx1c0V4dHJhTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS25vd25NYXBGaWVsZCIsICJVbmtub3duTWFwRmllbGQiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX0tub3duTWFwRmllbGRFbnRyeV9maWVsZEFjY2Vzc29yVGFibGUgPSBuZXcKICAgICAgY29tLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRNZXNzYWdlVjMuRmllbGRBY2Nlc3NvclRhYmxlKAogICAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfS25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZGVzY3JpcHRvciA9CiAgICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfZGVzY3JpcHRvci5nZXROZXN0ZWRUeXBlcygpLmdldCgxKTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0RW51bU1hcFBsdXNFeHRyYUxpdGVfVW5rbm93bk1hcEZpZWxkRW50cnlfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdEVudW1NYXBQbHVzRXh0cmFMaXRlX1Vua25vd25NYXBGaWVsZEVudHJ5X2Rlc2NyaXB0b3IsCiAgICAgICAgbmV3IGphdmEubGFuZy5TdHJpbmdbXSB7ICJLZXkiLCAiVmFsdWUiLCB9KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0TWVzc2FnZU1hcExpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoNSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiTWFwSW50MzJNZXNzYWdlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX01hcEludDMyTWVzc2FnZUVudHJ5X2Rlc2NyaXB0b3IgPQogICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX2Rlc2NyaXB0b3IuZ2V0TmVzdGVkVHlwZXMoKS5nZXQoMCk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdE1lc3NhZ2VNYXBMaXRlX01hcEludDMyTWVzc2FnZUVudHJ5X2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RNZXNzYWdlTWFwTGl0ZV9NYXBJbnQzMk1lc3NhZ2VFbnRyeV9kZXNjcmlwdG9yLAogICAgICAgIG5ldyBqYXZhLmxhbmcuU3RyaW5nW10geyAiS2V5IiwgIlZhbHVlIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfVGVzdFJlcXVpcmVkTGl0ZV9kZXNjcmlwdG9yID0KICAgICAgZ2V0RGVzY3JpcHRvcigpLmdldE1lc3NhZ2VUeXBlcygpLmdldCg2KTsKICAgIGludGVybmFsX3N0YXRpY19wcm90b2J1Zl91bml0dGVzdF9UZXN0UmVxdWlyZWRMaXRlX2ZpZWxkQWNjZXNzb3JUYWJsZSA9IG5ldwogICAgICBjb20uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZE1lc3NhZ2VWMy5GaWVsZEFjY2Vzc29yVGFibGUoCiAgICAgICAgaW50ZXJuYWxfc3RhdGljX3Byb3RvYnVmX3VuaXR0ZXN0X1Rlc3RSZXF1aXJlZExpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkEiLCAiQiIsICJDIiwgfSk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVfZGVzY3JpcHRvciA9CiAgICAgIGdldERlc2NyaXB0b3IoKS5nZXRNZXNzYWdlVHlwZXMoKS5nZXQoNyk7CiAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVfZmllbGRBY2Nlc3NvclRhYmxlID0gbmV3CiAgICAgIGNvbS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkTWVzc2FnZVYzLkZpZWxkQWNjZXNzb3JUYWJsZSgKICAgICAgICBpbnRlcm5hbF9zdGF0aWNfcHJvdG9idWZfdW5pdHRlc3RfRm9yZWlnbk1lc3NhZ2VBcmVuYUxpdGVfZGVzY3JpcHRvciwKICAgICAgICBuZXcgamF2YS5sYW5nLlN0cmluZ1tdIHsgIkMiLCB9KTsKICAgIGNvbS5nb29nbGUucHJvdG9idWYuVW5pdHRlc3RMaXRlLmdldERlc2NyaXB0b3IoKTsKICB9CgogIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChvdXRlcl9jbGFzc19zY29wZSkKfQpQSwECCgAKAAAAAAAAACEAJm8enzIAAAAyAAAAFAAAAAAAAAAAAAAAAAAAAAAATUVUQS1JTkYvTUFOSUZFU1QuTUZQSwECCgAKAAAAAAAAACEAXW6LNs5cAADOXAAAKwAAAAAAAAAAAAAAAABkAAAAY29tL2dvb2dsZS9wcm90b2J1Zi9Vbml0dGVzdEltcG9ydExpdGUuamF2YVBLAQIKAAoAAAAAAAAAIQAj9DSJ+FEAAPhRAAAxAAAAAAAAAAAAAAAAAHtdAABjb20vZ29vZ2xlL3Byb3RvYnVmL1VuaXR0ZXN0SW1wb3J0UHVibGljTGl0ZS5qYXZhUEsBAgoACgAAAAAAAAAhAErOg1K4sBoAuLAaACUAAAAAAAAAAAAAAAAAwq8AAGNvbS9nb29nbGUvcHJvdG9idWYvVW5pdHRlc3RMaXRlLmphdmFQSwECCgAKAAAAAAAAACEAMTRI9pz/CQCc/wkAJgAAAAAAAAAAAAAAAAC9YBsAcHJvdG9idWZfdW5pdHRlc3QvTWFwTGl0ZVVuaXR0ZXN0LmphdmFQSwUGAAAAAAUABQChAQAAnWAlAAAA