LyoKICogQ29weXJpZ2h0IDIwMDQtMjAwNiBTdW4gTWljcm9zeXN0ZW1zLCBJbmMuICBBbGwgUmlnaHRzIFJlc2VydmVkLgogKiBETyBOT1QgQUxURVIgT1IgUkVNT1ZFIENPUFlSSUdIVCBOT1RJQ0VTIE9SIFRISVMgRklMRSBIRUFERVIuCiAqCiAqIFRoaXMgY29kZSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CiAqIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvbiAyIG9ubHksIGFzCiAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLiAgU3VuIGRlc2lnbmF0ZXMgdGhpcwogKiBwYXJ0aWN1bGFyIGZpbGUgYXMgc3ViamVjdCB0byB0aGUgIkNsYXNzcGF0aCIgZXhjZXB0aW9uIGFzIHByb3ZpZGVkCiAqIGJ5IFN1biBpbiB0aGUgTElDRU5TRSBmaWxlIHRoYXQgYWNjb21wYW5pZWQgdGhpcyBjb2RlLgogKgogKiBUaGlzIGNvZGUgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVQKICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yCiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQogKiB2ZXJzaW9uIDIgZm9yIG1vcmUgZGV0YWlscyAoYSBjb3B5IGlzIGluY2x1ZGVkIGluIHRoZSBMSUNFTlNFIGZpbGUgdGhhdAogKiBhY2NvbXBhbmllZCB0aGlzIGNvZGUpLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uCiAqIDIgYWxvbmcgd2l0aCB0aGlzIHdvcms7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwKICogSW5jLiwgNTEgRnJhbmtsaW4gU3QsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEgVVNBLgogKgogKiBQbGVhc2UgY29udGFjdCBTdW4gTWljcm9zeXN0ZW1zLCBJbmMuLCA0MTUwIE5ldHdvcmsgQ2lyY2xlLCBTYW50YSBDbGFyYSwKICogQ0EgOTUwNTQgVVNBIG9yIHZpc2l0IHd3dy5zdW4uY29tIGlmIHlvdSBuZWVkIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gb3IKICogaGF2ZSBhbnkgcXVlc3Rpb25zLgogKi8KCnBhY2thZ2Ugc3VuLnRvb2xzLmpjb25zb2xlOwoKaW1wb3J0IGphdmEuYXd0Lio7CmltcG9ydCBqYXZhLmF3dC5ldmVudC4qOwppbXBvcnQgamF2YS5iZWFucy4qOwppbXBvcnQgamF2YS5pby4qOwppbXBvcnQgamF2YS5sYW5nLnJlZmxlY3QuKjsKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS51dGlsLkxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuVGltZXI7CgppbXBvcnQgamF2YXguc3dpbmcuKjsKaW1wb3J0IGphdmF4LnN3aW5nLnBsYWYuKjsKCmltcG9ydCBjb20uc3VuLnRvb2xzLmpjb25zb2xlLkpDb25zb2xlUGx1Z2luOwppbXBvcnQgY29tLnN1bi50b29scy5qY29uc29sZS5KQ29uc29sZUNvbnRleHQ7CmltcG9ydCBzdGF0aWMgY29tLnN1bi50b29scy5qY29uc29sZS5KQ29uc29sZUNvbnRleHQuQ29ubmVjdGlvblN0YXRlLio7CgppbXBvcnQgc3RhdGljIHN1bi50b29scy5qY29uc29sZS5Qcm94eUNsaWVudC4qOwoKQFN1cHByZXNzV2FybmluZ3MoInNlcmlhbCIpCnB1YmxpYyBjbGFzcyBWTVBhbmVsIGV4dGVuZHMgSlRhYmJlZFBhbmUgaW1wbGVtZW50cyBQcm9wZXJ0eUNoYW5nZUxpc3RlbmVyIHsKICAgIHByaXZhdGUgUHJveHlDbGllbnQgcHJveHlDbGllbnQ7CiAgICBwcml2YXRlIFRpbWVyIHRpbWVyOwogICAgcHJpdmF0ZSBpbnQgdXBkYXRlSW50ZXJ2YWw7CiAgICBwcml2YXRlIFN0cmluZyBob3N0TmFtZTsKICAgIHByaXZhdGUgaW50IHBvcnQ7CiAgICBwcml2YXRlIGludCB2bWlkOwogICAgcHJpdmF0ZSBTdHJpbmcgdXNlck5hbWU7CiAgICBwcml2YXRlIFN0cmluZyBwYXNzd29yZDsKICAgIHByaXZhdGUgU3RyaW5nIHVybDsKICAgIHByaXZhdGUgVk1JbnRlcm5hbEZyYW1lIHZtSUYgPSBudWxsOwoKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyB3aW5kb3dzTGFGID0KICAgICAgICAiY29tLnN1bi5qYXZhLnN3aW5nLnBsYWYud2luZG93cy5XaW5kb3dzTG9va0FuZEZlZWwiOwoKICAgIHByaXZhdGUgc3RhdGljIEFycmF5TGlzdDxUYWJJbmZvPiB0YWJJbmZvcyA9IG5ldyBBcnJheUxpc3Q8VGFiSW5mbz4oKTsKCiAgICBwcml2YXRlIGJvb2xlYW4gd2FzQ29ubmVjdGVkID0gZmFsc2U7CgogICAgLy8gVGhlIGV2ZXJDb25uZWN0ZWQgZmxhZyBrZWVwcyB0cmFjayBvZiB3aGV0aGVyIHRoZSB3aW5kb3cgY2FuIGJlCiAgICAvLyBjbG9zZWQgaWYgdGhlIHVzZXIgY2xpY2tzIENhbmNlbCBhZnRlciBhIGZhaWxlZCBjb25uZWN0aW9uIGF0dGVtcHQuCiAgICAvLwogICAgcHJpdmF0ZSBib29sZWFuIGV2ZXJDb25uZWN0ZWQgPSBmYWxzZTsKCiAgICAvLyBUaGUgaW5pdGlhbFVwZGF0ZSBmbGFnIGlzIHVzZWQgdG8gZW5hYmxlL2Rpc2FibGUgdGFicyBlYWNoIHRpbWUKICAgIC8vIGEgY29ubmVjdCBvciByZWNvbm5lY3QgdGFrZXMgcGxhY2UuIFRoaXMgZmxhZyBhdm9pZHMgaGF2aW5nIHRvCiAgICAvLyBlbmFibGUvZGlzYWJsZSB0YWJzIG9uIGVhY2ggdXBkYXRlIGNhbGwuCiAgICAvLwogICAgcHJpdmF0ZSBib29sZWFuIGluaXRpYWxVcGRhdGUgPSB0cnVlOwoKICAgIC8vIEVhY2ggVk1QYW5lbCBoYXMgaXRzIG93biBpbnN0YW5jZSBvZiB0aGUgSkNvbnNvbGVQbHVnaW4KICAgIC8vIEEgbWFwIG9mIEpDb25zb2xlUGx1Z2luIHRvIHRoZSBwcmV2aW91cyBTd2luZ1dvcmtlcgogICAgcHJpdmF0ZSBNYXA8SkNvbnNvbGVQbHVnaW4sIFN3aW5nV29ya2VyPD8sPz4+IHBsdWdpbnMgPSBudWxsOwogICAgcHJpdmF0ZSBib29sZWFuIHBsdWdpblRhYnNBZGRlZCA9IGZhbHNlOwoKICAgIC8vIFVwZGF0ZSB0aGVzZSBvbmx5IG9uIHRoZSBFRFQKICAgIHByaXZhdGUgSk9wdGlvblBhbmUgb3B0aW9uUGFuZTsKICAgIHByaXZhdGUgSlByb2dyZXNzQmFyIHByb2dyZXNzQmFyOwogICAgcHJpdmF0ZSBsb25nIHRpbWUwOwoKICAgIHN0YXRpYyB7CiAgICAgICAgdGFiSW5mb3MuYWRkKG5ldyBUYWJJbmZvKE92ZXJ2aWV3VGFiLmNsYXNzLCBPdmVydmlld1RhYi5nZXRUYWJOYW1lKCksIHRydWUpKTsKICAgICAgICB0YWJJbmZvcy5hZGQobmV3IFRhYkluZm8oTWVtb3J5VGFiLmNsYXNzLCAgTWVtb3J5VGFiLmdldFRhYk5hbWUoKSwgIHRydWUpKTsKICAgICAgICB0YWJJbmZvcy5hZGQobmV3IFRhYkluZm8oVGhyZWFkVGFiLmNsYXNzLCAgVGhyZWFkVGFiLmdldFRhYk5hbWUoKSwgIHRydWUpKTsKICAgICAgICB0YWJJbmZvcy5hZGQobmV3IFRhYkluZm8oQ2xhc3NUYWIuY2xhc3MsICAgQ2xhc3NUYWIuZ2V0VGFiTmFtZSgpLCAgIHRydWUpKTsKICAgICAgICB0YWJJbmZvcy5hZGQobmV3IFRhYkluZm8oU3VtbWFyeVRhYi5jbGFzcywgU3VtbWFyeVRhYi5nZXRUYWJOYW1lKCksIHRydWUpKTsKICAgICAgICB0YWJJbmZvcy5hZGQobmV3IFRhYkluZm8oTUJlYW5zVGFiLmNsYXNzLCAgTUJlYW5zVGFiLmdldFRhYk5hbWUoKSwgIHRydWUpKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIFRhYkluZm9bXSBnZXRUYWJJbmZvcygpIHsKICAgICAgICByZXR1cm4gdGFiSW5mb3MudG9BcnJheShuZXcgVGFiSW5mb1t0YWJJbmZvcy5zaXplKCldKTsKICAgIH0KCiAgICBWTVBhbmVsKFByb3h5Q2xpZW50IHByb3h5Q2xpZW50LCBpbnQgdXBkYXRlSW50ZXJ2YWwpIHsKICAgICAgICB0aGlzLnByb3h5Q2xpZW50ID0gcHJveHlDbGllbnQ7CiAgICAgICAgdGhpcy51cGRhdGVJbnRlcnZhbCA9IHVwZGF0ZUludGVydmFsOwogICAgICAgIHRoaXMuaG9zdE5hbWUgPSBwcm94eUNsaWVudC5nZXRIb3N0TmFtZSgpOwogICAgICAgIHRoaXMucG9ydCAgICAgPSBwcm94eUNsaWVudC5nZXRQb3J0KCk7CiAgICAgICAgdGhpcy52bWlkICAgICA9IHByb3h5Q2xpZW50LmdldFZtaWQoKTsKICAgICAgICB0aGlzLnVzZXJOYW1lID0gcHJveHlDbGllbnQuZ2V0VXNlck5hbWUoKTsKICAgICAgICB0aGlzLnBhc3N3b3JkID0gcHJveHlDbGllbnQuZ2V0UGFzc3dvcmQoKTsKICAgICAgICB0aGlzLnVybCA9IHByb3h5Q2xpZW50LmdldFVybCgpOwoKICAgICAgICBmb3IgKFRhYkluZm8gdGFiSW5mbyA6IHRhYkluZm9zKSB7CiAgICAgICAgICAgIGlmICh0YWJJbmZvLnRhYlZpc2libGUpIHsKICAgICAgICAgICAgICAgIGFkZFRhYih0YWJJbmZvKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcGx1Z2lucyA9IG5ldyBMaW5rZWRIYXNoTWFwPEpDb25zb2xlUGx1Z2luLCBTd2luZ1dvcmtlcjw/LD8+PigpOwogICAgICAgIGZvciAoSkNvbnNvbGVQbHVnaW4gcCA6IEpDb25zb2xlLmdldFBsdWdpbnMoKSkgewogICAgICAgICAgICBwLnNldENvbnRleHQocHJveHlDbGllbnQpOwogICAgICAgICAgICBwbHVnaW5zLnB1dChwLCBudWxsKTsKICAgICAgICB9CgogICAgICAgIFV0aWxpdGllcy51cGRhdGVUcmFuc3BhcmVuY3kodGhpcyk7CgogICAgICAgIFRvb2xUaXBNYW5hZ2VyLnNoYXJlZEluc3RhbmNlKCkucmVnaXN0ZXJDb21wb25lbnQodGhpcyk7CgogICAgICAgIC8vIFN0YXJ0IGxpc3RlbmluZyB0byBjb25uZWN0aW9uIHN0YXRlIGV2ZW50cwogICAgICAgIC8vCiAgICAgICAgcHJveHlDbGllbnQuYWRkUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcih0aGlzKTsKCiAgICAgICAgYWRkTW91c2VMaXN0ZW5lcihuZXcgTW91c2VBZGFwdGVyKCkgewogICAgICAgICAgICBwdWJsaWMgdm9pZCBtb3VzZUNsaWNrZWQoTW91c2VFdmVudCBlKSB7CiAgICAgICAgICAgICAgICBpZiAoY29ubmVjdGVkSWNvbkJvdW5kcyAhPSBudWxsCiAgICAgICAgICAgICAgICAgICAgJiYgKGUuZ2V0TW9kaWZpZXJzKCkgJiBNb3VzZUV2ZW50LkJVVFRPTjFfTUFTSykgIT0gMAogICAgICAgICAgICAgICAgICAgICYmIGNvbm5lY3RlZEljb25Cb3VuZHMuY29udGFpbnMoZS5nZXRQb2ludCgpKSkgewoKICAgICAgICAgICAgICAgICAgICBpZiAoaXNDb25uZWN0ZWQoKSkgewogICAgICAgICAgICAgICAgICAgICAgICBkaXNjb25uZWN0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHdhc0Nvbm5lY3RlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3QoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVwYWludCgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSk7CgogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIEljb24gY29ubmVjdGVkSWNvbjE2ID0KICAgICAgICBuZXcgSW1hZ2VJY29uKFZNUGFuZWwuY2xhc3MuZ2V0UmVzb3VyY2UoInJlc291cmNlcy9jb25uZWN0ZWQxNi5wbmciKSk7CiAgICBwcml2YXRlIHN0YXRpYyBJY29uIGNvbm5lY3RlZEljb24yNCA9CiAgICAgICAgbmV3IEltYWdlSWNvbihWTVBhbmVsLmNsYXNzLmdldFJlc291cmNlKCJyZXNvdXJjZXMvY29ubmVjdGVkMjQucG5nIikpOwogICAgcHJpdmF0ZSBzdGF0aWMgSWNvbiBkaXNjb25uZWN0ZWRJY29uMTYgPQogICAgICAgIG5ldyBJbWFnZUljb24oVk1QYW5lbC5jbGFzcy5nZXRSZXNvdXJjZSgicmVzb3VyY2VzL2Rpc2Nvbm5lY3RlZDE2LnBuZyIpKTsKICAgIHByaXZhdGUgc3RhdGljIEljb24gZGlzY29ubmVjdGVkSWNvbjI0ID0KICAgICAgICBuZXcgSW1hZ2VJY29uKFZNUGFuZWwuY2xhc3MuZ2V0UmVzb3VyY2UoInJlc291cmNlcy9kaXNjb25uZWN0ZWQyNC5wbmciKSk7CgogICAgcHJpdmF0ZSBSZWN0YW5nbGUgY29ubmVjdGVkSWNvbkJvdW5kczsKCiAgICAvLyBPdmVycmlkZSB0byBpbmNyZWFzZSByaWdodCBpbnNldCBmb3IgdGFiIGFyZWEsCiAgICAvLyBpbiBvcmRlciB0byByZXNlcnZlIHNwYWNlIGZvciB0aGUgY29ubmVjdCB0b2dnbGUuCiAgICBwdWJsaWMgdm9pZCBzZXRVSShUYWJiZWRQYW5lVUkgdWkpIHsKICAgICAgICBJbnNldHMgaW5zZXRzID0gKEluc2V0cylVSU1hbmFnZXIuZ2V0TG9va0FuZEZlZWxEZWZhdWx0cygpLmdldCgiVGFiYmVkUGFuZS50YWJBcmVhSW5zZXRzIik7CiAgICAgICAgaW5zZXRzID0gKEluc2V0cylpbnNldHMuY2xvbmUoKTsKICAgICAgICBpbnNldHMucmlnaHQgKz0gY29ubmVjdGVkSWNvbjI0LmdldEljb25XaWR0aCgpICsgODsKICAgICAgICBVSU1hbmFnZXIucHV0KCJUYWJiZWRQYW5lLnRhYkFyZWFJbnNldHMiLCBpbnNldHMpOwogICAgICAgIHN1cGVyLnNldFVJKHVpKTsKICAgIH0KCiAgICAvLyBPdmVycmlkZSB0byBwYWludCB0aGUgY29ubmVjdCB0b2dnbGUKICAgIHByb3RlY3RlZCB2b2lkIHBhaW50Q29tcG9uZW50KEdyYXBoaWNzIGcpIHsKICAgICAgICBzdXBlci5wYWludENvbXBvbmVudChnKTsKCiAgICAgICAgSWNvbiBpY29uOwogICAgICAgIENvbXBvbmVudCBjMCA9IGdldENvbXBvbmVudCgwKTsKICAgICAgICBpZiAoYzAgIT0gbnVsbCAmJiBjMC5nZXRZKCkgPiAyNCkgewogICAgICAgICAgICBpY29uID0gaXNDb25uZWN0ZWQoKSA/IGNvbm5lY3RlZEljb24yNCA6IGRpc2Nvbm5lY3RlZEljb24yNDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpY29uID0gaXNDb25uZWN0ZWQoKSA/IGNvbm5lY3RlZEljb24xNiA6IGRpc2Nvbm5lY3RlZEljb24xNjsKICAgICAgICB9CiAgICAgICAgSW5zZXRzIGluc2V0cyA9IGdldEluc2V0cygpOwogICAgICAgIGludCB4ID0gZ2V0V2lkdGgoKSAtIGluc2V0cy5yaWdodCAtIGljb24uZ2V0SWNvbldpZHRoKCkgLSA0OwogICAgICAgIGludCB5ID0gaW5zZXRzLnRvcDsKICAgICAgICBpZiAoYzAgIT0gbnVsbCkgewogICAgICAgICAgICB5ID0gKGMwLmdldFkoKSAtIGljb24uZ2V0SWNvbkhlaWdodCgpKSAvIDI7CiAgICAgICAgfQogICAgICAgIGljb24ucGFpbnRJY29uKHRoaXMsIGcsIHgsIHkpOwogICAgICAgIGNvbm5lY3RlZEljb25Cb3VuZHMgPSBuZXcgUmVjdGFuZ2xlKHgsIHksIGljb24uZ2V0SWNvbldpZHRoKCksIGljb24uZ2V0SWNvbkhlaWdodCgpKTsKICAgIH0KCiAgICBwdWJsaWMgU3RyaW5nIGdldFRvb2xUaXBUZXh0KE1vdXNlRXZlbnQgZXZlbnQpIHsKICAgICAgICBpZiAoY29ubmVjdGVkSWNvbkJvdW5kcy5jb250YWlucyhldmVudC5nZXRQb2ludCgpKSkgewogICAgICAgICAgICBpZiAoaXNDb25uZWN0ZWQoKSkgewogICAgICAgICAgICAgICAgcmV0dXJuIGdldFRleHQoIkNvbm5lY3RlZC4gQ2xpY2sgdG8gZGlzY29ubmVjdC4iKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHJldHVybiBnZXRUZXh0KCJEaXNjb25uZWN0ZWQuIENsaWNrIHRvIGNvbm5lY3QuIik7CiAgICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gc3VwZXIuZ2V0VG9vbFRpcFRleHQoZXZlbnQpOwogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIHN5bmNocm9uaXplZCB2b2lkIGFkZFRhYihUYWJJbmZvIHRhYkluZm8pIHsKICAgICAgICBUYWIgdGFiID0gaW5zdGFudGlhdGUodGFiSW5mbyk7CiAgICAgICAgaWYgKHRhYiAhPSBudWxsKSB7CiAgICAgICAgICAgIGFkZFRhYih0YWJJbmZvLm5hbWUsIHRhYik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGFiSW5mby50YWJWaXNpYmxlID0gZmFsc2U7CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgc3luY2hyb25pemVkIHZvaWQgaW5zZXJ0VGFiKFRhYkluZm8gdGFiSW5mbywgaW50IGluZGV4KSB7CiAgICAgICAgVGFiIHRhYiA9IGluc3RhbnRpYXRlKHRhYkluZm8pOwogICAgICAgIGlmICh0YWIgIT0gbnVsbCkgewogICAgICAgICAgICBpbnNlcnRUYWIodGFiSW5mby5uYW1lLCBudWxsLCB0YWIsIG51bGwsIGluZGV4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0YWJJbmZvLnRhYlZpc2libGUgPSBmYWxzZTsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIHN5bmNocm9uaXplZCB2b2lkIHJlbW92ZVRhYkF0KGludCBpbmRleCkgewogICAgICAgIHN1cGVyLnJlbW92ZVRhYkF0KGluZGV4KTsKICAgIH0KCiAgICBwcml2YXRlIFRhYiBpbnN0YW50aWF0ZShUYWJJbmZvIHRhYkluZm8pIHsKICAgICAgICB0cnkgewogICAgICAgICAgICBDb25zdHJ1Y3RvciBjb24gPSB0YWJJbmZvLnRhYkNsYXNzLmdldENvbnN0cnVjdG9yKFZNUGFuZWwuY2xhc3MpOwogICAgICAgICAgICByZXR1cm4gKFRhYiljb24ubmV3SW5zdGFuY2UodGhpcyk7CiAgICAgICAgfSBjYXRjaCAoRXhjZXB0aW9uIGV4KSB7CiAgICAgICAgICAgIFN5c3RlbS5lcnIucHJpbnRsbihleCk7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgIH0KCiAgICBib29sZWFuIGlzQ29ubmVjdGVkKCkgewogICAgICAgIHJldHVybiBwcm94eUNsaWVudC5pc0Nvbm5lY3RlZCgpOwogICAgfQoKICAgIHB1YmxpYyBpbnQgZ2V0VXBkYXRlSW50ZXJ2YWwoKSB7CiAgICAgICAgcmV0dXJuIHVwZGF0ZUludGVydmFsOwogICAgfQoKICAgIC8qKgogICAgICogV0FSTklORyBORVZFUiBDQUxMIFRISVMgTUVUSE9EIFRPIE1BS0UgSk1YIFJFUVVFU1QKICAgICAqIElGICBhc3NlcnRUaHJlYWQgPT0gZmFsc2UuCiAgICAgKiBESVNQQVRDSEVSIFRIUkVBRCBJUyBOT1QgQVNTRVJURUQuCiAgICAgKiBJVCBJUyBVU0VEIFRPIE1BS0UgU09NRSBMT0NBTCBNQU5JUFVMQVRJT05TLgogICAgICovCiAgICBQcm94eUNsaWVudCBnZXRQcm94eUNsaWVudChib29sZWFuIGFzc2VydFRocmVhZCkgewogICAgICAgIGlmKGFzc2VydFRocmVhZCkKICAgICAgICAgICAgcmV0dXJuIGdldFByb3h5Q2xpZW50KCk7CiAgICAgICAgZWxzZQogICAgICAgICAgICByZXR1cm4gcHJveHlDbGllbnQ7CiAgICB9CgogICAgcHVibGljIFByb3h5Q2xpZW50IGdldFByb3h5Q2xpZW50KCkgewogICAgICAgIFN0cmluZyB0aHJlYWRDbGFzcyA9IFRocmVhZC5jdXJyZW50VGhyZWFkKCkuZ2V0Q2xhc3MoKS5nZXROYW1lKCk7CiAgICAgICAgaWYgKHRocmVhZENsYXNzLmVxdWFscygiamF2YS5hd3QuRXZlbnREaXNwYXRjaFRocmVhZCIpKSB7CiAgICAgICAgICAgIFN0cmluZyBtc2cgPSAiQ2FsbGluZyBWTVBhbmVsLmdldFByb3h5Q2xpZW50KCkgZnJvbSB0aGUgRXZlbnQgRGlzcGF0Y2ggVGhyZWFkISI7CiAgICAgICAgICAgIG5ldyBSdW50aW1lRXhjZXB0aW9uKG1zZykucHJpbnRTdGFja1RyYWNlKCk7CiAgICAgICAgICAgIFN5c3RlbS5leGl0KDEpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcHJveHlDbGllbnQ7CiAgICB9CgogICAgcHVibGljIHZvaWQgY2xlYW5VcCgpIHsKICAgICAgICAvL3Byb3h5Q2xpZW50LmRpc2Nvbm5lY3QoKTsKICAgICAgICBmb3IgKFRhYiB0YWIgOiBnZXRUYWJzKCkpIHsKICAgICAgICAgICAgdGFiLmRpc3Bvc2UoKTsKICAgICAgICB9CiAgICAgICAgZm9yIChKQ29uc29sZVBsdWdpbiBwIDogcGx1Z2lucy5rZXlTZXQoKSkgewogICAgICAgICAgICBwLmRpc3Bvc2UoKTsKICAgICAgICB9CiAgICAgICAgLy8gQ2FuY2VsIHBlbmRpbmcgdXBkYXRlIHRhc2tzCiAgICAgICAgLy8KICAgICAgICBpZiAodGltZXIgIT0gbnVsbCkgewogICAgICAgICAgICB0aW1lci5jYW5jZWwoKTsKICAgICAgICB9CiAgICAgICAgLy8gU3RvcCBsaXN0ZW5pbmcgdG8gY29ubmVjdGlvbiBzdGF0ZSBldmVudHMKICAgICAgICAvLwogICAgICAgIHByb3h5Q2xpZW50LnJlbW92ZVByb3BlcnR5Q2hhbmdlTGlzdGVuZXIodGhpcyk7CiAgICB9CgogICAgLy8gQ2FsbCBvbiBFRFQKICAgIHB1YmxpYyB2b2lkIGNvbm5lY3QoKSB7CiAgICAgICAgaWYgKGlzQ29ubmVjdGVkKCkpIHsKICAgICAgICAgICAgLy8gY3JlYXRlIHBsdWdpbiB0YWJzIGlmIG5vdCBkb25lCiAgICAgICAgICAgIGNyZWF0ZVBsdWdpblRhYnMoKTsKICAgICAgICAgICAgLy8gTm90aWZ5IHRhYnMKICAgICAgICAgICAgZmlyZUNvbm5lY3RlZENoYW5nZSh0cnVlKTsKICAgICAgICAgICAgLy8gRW5hYmxlL2Rpc2FibGUgdGFicyBvbiBpbml0aWFsIHVwZGF0ZQogICAgICAgICAgICBpbml0aWFsVXBkYXRlID0gdHJ1ZTsKICAgICAgICAgICAgLy8gU3RhcnQvUmVzdGFydCB1cGRhdGUgdGltZXIgb24gY29ubmVjdC9yZWNvbm5lY3QKICAgICAgICAgICAgc3RhcnRVcGRhdGVUaW1lcigpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG5ldyBUaHJlYWQoIlZNUGFuZWwuY29ubmVjdCIpIHsKICAgICAgICAgICAgICAgIHB1YmxpYyB2b2lkIHJ1bigpIHsKICAgICAgICAgICAgICAgICAgICBwcm94eUNsaWVudC5jb25uZWN0KCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0uc3RhcnQoKTsKICAgICAgICB9CiAgICB9CgoKICAgIC8vIENhbGwgb24gRURUCiAgICBwdWJsaWMgdm9pZCBkaXNjb25uZWN0KCkgewogICAgICAgIHByb3h5Q2xpZW50LmRpc2Nvbm5lY3QoKTsKICAgICAgICB1cGRhdGVGcmFtZVRpdGxlKCk7CiAgICB9CgoKCiAgICAvLyBDYWxsZWQgb24gRURUCiAgICBwdWJsaWMgdm9pZCBwcm9wZXJ0eUNoYW5nZShQcm9wZXJ0eUNoYW5nZUV2ZW50IGV2KSB7CiAgICAgICAgU3RyaW5nIHByb3AgPSBldi5nZXRQcm9wZXJ0eU5hbWUoKTsKCiAgICAgICAgaWYgKHByb3AgPT0gQ09OTkVDVElPTl9TVEFURV9QUk9QRVJUWSkgewogICAgICAgICAgICBDb25uZWN0aW9uU3RhdGUgb2xkU3RhdGUgPSAoQ29ubmVjdGlvblN0YXRlKWV2LmdldE9sZFZhbHVlKCk7CiAgICAgICAgICAgIENvbm5lY3Rpb25TdGF0ZSBuZXdTdGF0ZSA9IChDb25uZWN0aW9uU3RhdGUpZXYuZ2V0TmV3VmFsdWUoKTsKICAgICAgICAgICAgc3dpdGNoIChuZXdTdGF0ZSkgewogICAgICAgICAgICAgIGNhc2UgQ09OTkVDVElORzoKICAgICAgICAgICAgICAgIG9uQ29ubmVjdGluZygpOwogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICAgIGNhc2UgQ09OTkVDVEVEOgogICAgICAgICAgICAgICAgaWYgKHByb2dyZXNzQmFyICE9IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICBwcm9ncmVzc0Jhci5zZXRJbmRldGVybWluYXRlKGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICBwcm9ncmVzc0Jhci5zZXRWYWx1ZSgxMDApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xvc2VPcHRpb25QYW5lKCk7CiAgICAgICAgICAgICAgICB1cGRhdGVGcmFtZVRpdGxlKCk7CiAgICAgICAgICAgICAgICAvLyBjcmVhdGUgdGFicyBpZiBub3QgZG9uZQogICAgICAgICAgICAgICAgY3JlYXRlUGx1Z2luVGFicygpOwogICAgICAgICAgICAgICAgcmVwYWludCgpOwogICAgICAgICAgICAgICAgLy8gTm90aWZ5IHRhYnMKICAgICAgICAgICAgICAgIGZpcmVDb25uZWN0ZWRDaGFuZ2UodHJ1ZSk7CiAgICAgICAgICAgICAgICAvLyBFbmFibGUvZGlzYWJsZSB0YWJzIG9uIGluaXRpYWwgdXBkYXRlCiAgICAgICAgICAgICAgICBpbml0aWFsVXBkYXRlID0gdHJ1ZTsKICAgICAgICAgICAgICAgIC8vIFN0YXJ0L1Jlc3RhcnQgdXBkYXRlIHRpbWVyIG9uIGNvbm5lY3QvcmVjb25uZWN0CiAgICAgICAgICAgICAgICBzdGFydFVwZGF0ZVRpbWVyKCk7CiAgICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgICAgY2FzZSBESVNDT05ORUNURUQ6CiAgICAgICAgICAgICAgICBpZiAocHJvZ3Jlc3NCYXIgIT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgIHByb2dyZXNzQmFyLnNldEluZGV0ZXJtaW5hdGUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgIHByb2dyZXNzQmFyLnNldFZhbHVlKDApOwogICAgICAgICAgICAgICAgICAgIGNsb3NlT3B0aW9uUGFuZSgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdm1QYW5lbERpZWQoKTsKICAgICAgICAgICAgICAgIGlmIChvbGRTdGF0ZSA9PSBDb25uZWN0aW9uU3RhdGUuQ09OTkVDVEVEKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gTm90aWZ5IHRhYnMKICAgICAgICAgICAgICAgICAgICBmaXJlQ29ubmVjdGVkQ2hhbmdlKGZhbHNlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKCgogICAgLy8gQ2FsbGVkIG9uIEVEVAogICAgcHJpdmF0ZSB2b2lkIG9uQ29ubmVjdGluZygpIHsKICAgICAgICB0aW1lMCA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoKICAgICAgICBmaW5hbCBKQ29uc29sZSBqYyA9IChKQ29uc29sZSlTd2luZ1V0aWxpdGllcy5nZXRXaW5kb3dBbmNlc3Rvcih0aGlzKTsKCiAgICAgICAgU3RyaW5nIGNvbm5lY3Rpb25OYW1lID0gZ2V0Q29ubmVjdGlvbk5hbWUoKTsKICAgICAgICBwcm9ncmVzc0JhciA9IG5ldyBKUHJvZ3Jlc3NCYXIoKTsKICAgICAgICBwcm9ncmVzc0Jhci5zZXRJbmRldGVybWluYXRlKHRydWUpOwogICAgICAgIEpQYW5lbCBwcm9ncmVzc1BhbmVsID0gbmV3IEpQYW5lbChuZXcgRmxvd0xheW91dChGbG93TGF5b3V0LkNFTlRFUikpOwogICAgICAgIHByb2dyZXNzUGFuZWwuYWRkKHByb2dyZXNzQmFyKTsKCiAgICAgICAgT2JqZWN0W10gbWVzc2FnZSA9IHsKICAgICAgICAgICAgIjxodG1sPjxoMz4iICsgZ2V0VGV4dCgiY29ubmVjdGluZ1RvMSIsIGNvbm5lY3Rpb25OYW1lKSArICI8L2gzPjwvaHRtbD4iLAogICAgICAgICAgICBwcm9ncmVzc1BhbmVsLAogICAgICAgICAgICAiPGh0bWw+PGI+IiAgKyBnZXRUZXh0KCJjb25uZWN0aW5nVG8yIiwgY29ubmVjdGlvbk5hbWUpICsgIjwvYj48L2h0bWw+IgogICAgICAgIH07CgoKICAgICAgICBvcHRpb25QYW5lID0KICAgICAgICAgICAgU2hlZXREaWFsb2cuc2hvd09wdGlvbkRpYWxvZyh0aGlzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSk9wdGlvblBhbmUuREVGQVVMVF9PUFRJT04sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSk9wdGlvblBhbmUuSU5GT1JNQVRJT05fTUVTU0FHRSwgbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgU3RyaW5nW10geyBnZXRUZXh0KCJDYW5jZWwiKSB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDApOwoKCiAgICB9CgogICAgLy8gQ2FsbGVkIG9uIEVEVAogICAgcHJpdmF0ZSB2b2lkIGNsb3NlT3B0aW9uUGFuZSgpIHsKICAgICAgICBpZiAob3B0aW9uUGFuZSAhPSBudWxsKSB7CiAgICAgICAgICAgIG5ldyBUaHJlYWQoIlZNUGFuZWwuc2xlZXBlciIpIHsKICAgICAgICAgICAgICAgIHB1YmxpYyB2b2lkIHJ1bigpIHsKICAgICAgICAgICAgICAgICAgICBsb25nIGVsYXBzZWQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSAtIHRpbWUwOwogICAgICAgICAgICAgICAgICAgIGlmIChlbGFwc2VkIDwgMjAwMCkgewogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xlZXAoMjAwMCAtIGVsYXBzZWQpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChJbnRlcnJ1cHRlZEV4Y2VwdGlvbiBleCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWdub3JlCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgU3dpbmdVdGlsaXRpZXMuaW52b2tlTGF0ZXIobmV3IFJ1bm5hYmxlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBwdWJsaWMgdm9pZCBydW4oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25QYW5lLnNldFZpc2libGUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3NCYXIgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0uc3RhcnQoKTsKICAgICAgICB9CiAgICB9CgogICAgdm9pZCB1cGRhdGVGcmFtZVRpdGxlKCkgewogICAgICAgIFZNSW50ZXJuYWxGcmFtZSB2bUlGID0gZ2V0RnJhbWUoKTsKICAgICAgICBpZiAodm1JRiAhPSBudWxsKSB7CiAgICAgICAgICAgIFN0cmluZyBkaXNwbGF5TmFtZSA9IGdldERpc3BsYXlOYW1lKCk7CiAgICAgICAgICAgIGlmICghcHJveHlDbGllbnQuaXNDb25uZWN0ZWQoKSkgewogICAgICAgICAgICAgICAgZGlzcGxheU5hbWUgPSBnZXRUZXh0KCJDb25uZWN0aW9uTmFtZSAoZGlzY29ubmVjdGVkKSIsIGRpc3BsYXlOYW1lKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2bUlGLnNldFRpdGxlKGRpc3BsYXlOYW1lKTsKICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBWTUludGVybmFsRnJhbWUgZ2V0RnJhbWUoKSB7CiAgICAgICAgaWYgKHZtSUYgPT0gbnVsbCkgewogICAgICAgICAgICB2bUlGID0gKFZNSW50ZXJuYWxGcmFtZSlTd2luZ1V0aWxpdGllcy5nZXRBbmNlc3Rvck9mQ2xhc3MoVk1JbnRlcm5hbEZyYW1lLmNsYXNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB2bUlGOwogICAgfQoKICAgIC8vIFRPRE86IHRoaXMgbWV0aG9kIGlzIG5vdCBuZWVkZWQgd2hlbiBhbGwgSkNvbnNvbGUgdGFicwogICAgLy8gYXJlIG1pZ3JhdGVkIHRvIHVzZSB0aGUgbmV3IEpDb25zb2xlUGx1Z2luIEFQSS4KICAgIC8vCiAgICAvLyBBIHRocmVhZCBzYWZlIGNsb25lIG9mIGFsbCBKQ29uc29sZSB0YWJzCiAgICBzeW5jaHJvbml6ZWQgTGlzdDxUYWI+IGdldFRhYnMoKSB7CiAgICAgICAgQXJyYXlMaXN0PFRhYj4gbGlzdCA9IG5ldyBBcnJheUxpc3Q8VGFiPigpOwogICAgICAgIGludCBuID0gZ2V0VGFiQ291bnQoKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgICAgICBDb21wb25lbnQgYyA9IGdldENvbXBvbmVudEF0KGkpOwogICAgICAgICAgICBpZiAoYyBpbnN0YW5jZW9mIFRhYikgewogICAgICAgICAgICAgICAgbGlzdC5hZGQoKFRhYikgYyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGxpc3Q7CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIHN0YXJ0VXBkYXRlVGltZXIoKSB7CiAgICAgICAgaWYgKHRpbWVyICE9IG51bGwpIHsKICAgICAgICAgICAgdGltZXIuY2FuY2VsKCk7CiAgICAgICAgfQogICAgICAgIFRpbWVyVGFzayB0aW1lclRhc2sgPSBuZXcgVGltZXJUYXNrKCkgewogICAgICAgICAgICBwdWJsaWMgdm9pZCBydW4oKSB7CiAgICAgICAgICAgICAgICB1cGRhdGUoKTsKICAgICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgU3RyaW5nIHRpbWVyTmFtZSA9ICJUaW1lci0iK2dldENvbm5lY3Rpb25OYW1lKCk7CiAgICAgICAgdGltZXIgPSBuZXcgVGltZXIodGltZXJOYW1lLCB0cnVlKTsKICAgICAgICB0aW1lci5zY2hlZHVsZSh0aW1lclRhc2ssIDAsIHVwZGF0ZUludGVydmFsKTsKICAgIH0KCgogICAgLy8gQ2FsbCBvbiBFRFQKICAgIHByaXZhdGUgdm9pZCB2bVBhbmVsRGllZCgpIHsKICAgICAgICBkaXNjb25uZWN0KCk7CgogICAgICAgIGZpbmFsIEpDb25zb2xlIGpjID0gKEpDb25zb2xlKVN3aW5nVXRpbGl0aWVzLmdldFdpbmRvd0FuY2VzdG9yKHRoaXMpOwoKICAgICAgICBKT3B0aW9uUGFuZSBvcHRpb25QYW5lOwoKICAgICAgICBmaW5hbCBTdHJpbmcgY29ubmVjdFN0ciAgID0gZ2V0VGV4dCgiQ29ubmVjdCIpOwogICAgICAgIGZpbmFsIFN0cmluZyByZWNvbm5lY3RTdHIgPSBnZXRUZXh0KCJSZWNvbm5lY3QiKTsKICAgICAgICBmaW5hbCBTdHJpbmcgY2FuY2VsU3RyICAgID0gZ2V0VGV4dCgiQ2FuY2VsIik7CgogICAgICAgIFN0cmluZyBtc2dUaXRsZSwgbXNnRXhwbGFuYXRpb24sIGJ1dHRvblN0cjsKCiAgICAgICAgaWYgKHdhc0Nvbm5lY3RlZCkgewogICAgICAgICAgICB3YXNDb25uZWN0ZWQgPSBmYWxzZTsKICAgICAgICAgICAgbXNnVGl0bGUgPSBnZXRUZXh0KCJjb25uZWN0aW9uTG9zdDEiKTsKICAgICAgICAgICAgbXNnRXhwbGFuYXRpb24gPSBnZXRUZXh0KCJjb25uZWN0aW9uTG9zdDIiLCBnZXRDb25uZWN0aW9uTmFtZSgpKTsKICAgICAgICAgICAgYnV0dG9uU3RyID0gcmVjb25uZWN0U3RyOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG1zZ1RpdGxlID0gZ2V0VGV4dCgiY29ubmVjdGlvbkZhaWxlZDEiKTsKICAgICAgICAgICAgbXNnRXhwbGFuYXRpb24gPSBnZXRUZXh0KCJjb25uZWN0aW9uRmFpbGVkMiIsIGdldENvbm5lY3Rpb25OYW1lKCkpOwogICAgICAgICAgICBidXR0b25TdHIgPSBjb25uZWN0U3RyOwogICAgICAgIH0KCiAgICAgICAgb3B0aW9uUGFuZSA9CiAgICAgICAgICAgIFNoZWV0RGlhbG9nLnNob3dPcHRpb25EaWFsb2codGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGh0bWw+PGgzPiIgKyBtc2dUaXRsZSArICI8L2gzPiIgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj4iICsgbXNnRXhwbGFuYXRpb24gKyAiPC9iPiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSk9wdGlvblBhbmUuREVGQVVMVF9PUFRJT04sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSk9wdGlvblBhbmUuV0FSTklOR19NRVNTQUdFLCBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBTdHJpbmdbXSB7IGJ1dHRvblN0ciwgY2FuY2VsU3RyIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMCk7CgogICAgICAgIG9wdGlvblBhbmUuYWRkUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcihuZXcgUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcigpIHsKICAgICAgICAgICAgcHVibGljIHZvaWQgcHJvcGVydHlDaGFuZ2UoUHJvcGVydHlDaGFuZ2VFdmVudCBldmVudCkgewogICAgICAgICAgICAgICAgaWYgKGV2ZW50LmdldFByb3BlcnR5TmFtZSgpLmVxdWFscyhKT3B0aW9uUGFuZS5WQUxVRV9QUk9QRVJUWSkpIHsKICAgICAgICAgICAgICAgICAgICBPYmplY3QgdmFsdWUgPSBldmVudC5nZXROZXdWYWx1ZSgpOwoKICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPT0gcmVjb25uZWN0U3RyIHx8IHZhbHVlID09IGNvbm5lY3RTdHIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdCgpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWV2ZXJDb25uZWN0ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEZyYW1lKCkuc2V0Q2xvc2VkKHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChQcm9wZXJ0eVZldG9FeGNlcHRpb24gZXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNob3VsZCBub3QgaGFwcGVuLCBidXQgY2FuIGJlIGlnbm9yZWQuCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgIH0KCiAgICAvLyBOb3RlOiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgb24gYSBUaW1lclRhc2sgdGhyZWFkLiBBbnkgR1VJIG1hbmlwdWxhdGlvbgogICAgLy8gbXVzdCBiZSBwZXJmb3JtZWQgd2l0aCBpbnZva2VMYXRlcigpIG9yIGludm9rZUFuZFdhaXQoKS4KICAgIHByaXZhdGUgT2JqZWN0IGxvY2tPYmplY3QgPSBuZXcgT2JqZWN0KCk7CiAgICBwcml2YXRlIHZvaWQgdXBkYXRlKCkgewogICAgICAgIHN5bmNocm9uaXplZChsb2NrT2JqZWN0KSB7CiAgICAgICAgICAgIGlmICghaXNDb25uZWN0ZWQoKSkgewogICAgICAgICAgICAgICAgaWYgKHdhc0Nvbm5lY3RlZCkgewogICAgICAgICAgICAgICAgICAgIEV2ZW50UXVldWUuaW52b2tlTGF0ZXIobmV3IFJ1bm5hYmxlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBwdWJsaWMgdm9pZCBydW4oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2bVBhbmVsRGllZCgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3YXNDb25uZWN0ZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHdhc0Nvbm5lY3RlZCA9IHRydWU7CiAgICAgICAgICAgICAgICBldmVyQ29ubmVjdGVkID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBwcm94eUNsaWVudC5mbHVzaCgpOwogICAgICAgICAgICBMaXN0PFRhYj4gdGFicyA9IGdldFRhYnMoKTsKICAgICAgICAgICAgZmluYWwgaW50IG4gPSB0YWJzLnNpemUoKTsKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICAgICAgICAgIGZpbmFsIGludCBpbmRleCA9IGk7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIGlmICghcHJveHlDbGllbnQuaXNEZWFkKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRhYgogICAgICAgICAgICAgICAgICAgICAgICAvLwogICAgICAgICAgICAgICAgICAgICAgICB0YWJzLmdldChpbmRleCkudXBkYXRlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVuYWJsZSB0YWIgb24gaW5pdGlhbCB1cGRhdGUKICAgICAgICAgICAgICAgICAgICAgICAgLy8KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluaXRpYWxVcGRhdGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UXVldWUuaW52b2tlTGF0ZXIobmV3IFJ1bm5hYmxlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1YmxpYyB2b2lkIHJ1bigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0RW5hYmxlZEF0KGluZGV4LCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gRGlzYWJsZSB0YWIgb24gaW5pdGlhbCB1cGRhdGUKICAgICAgICAgICAgICAgICAgICAvLwogICAgICAgICAgICAgICAgICAgIGlmIChpbml0aWFsVXBkYXRlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UXVldWUuaW52b2tlTGF0ZXIobmV3IFJ1bm5hYmxlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHVibGljIHZvaWQgcnVuKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldEVuYWJsZWRBdChpbmRleCwgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIHBsdWdpbiBHVUkgdXBkYXRlCiAgICAgICAgICAgIGZvciAoSkNvbnNvbGVQbHVnaW4gcCA6IHBsdWdpbnMua2V5U2V0KCkpIHsKICAgICAgICAgICAgICAgIFN3aW5nV29ya2VyPD8sPz4gc3cgPSBwLm5ld1N3aW5nV29ya2VyKCk7CiAgICAgICAgICAgICAgICBTd2luZ1dvcmtlcjw/LD8+IHByZXZTVyA9IHBsdWdpbnMuZ2V0KHApOwogICAgICAgICAgICAgICAgLy8gc2NoZWR1bGUgU3dpbmdXb3JrZXIgdG8gcnVuIG9ubHkgaWYgdGhlIHByZXZpb3VzCiAgICAgICAgICAgICAgICAvLyBTd2luZ1dvcmtlciBoYXMgZmluaXNoZWQgaXRzIHRhc2sgYW5kIGl0IGhhc24ndCBzdGFydGVkLgogICAgICAgICAgICAgICAgaWYgKHByZXZTVyA9PSBudWxsIHx8IHByZXZTVy5pc0RvbmUoKSkgewogICAgICAgICAgICAgICAgICAgIGlmIChzdyA9PSBudWxsIHx8IHN3LmdldFN0YXRlKCkgPT0gU3dpbmdXb3JrZXIuU3RhdGVWYWx1ZS5QRU5ESU5HKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBsdWdpbnMucHV0KHAsIHN3KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN3ICE9IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3LmV4ZWN1dGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gU2V0IHRoZSBmaXJzdCBlbmFibGVkIHRhYiBpbiB0aGUgdGFitHMgbGlzdAogICAgICAgICAgICAvLyBhcyB0aGUgc2VsZWN0ZWQgdGFiIG9uIGluaXRpYWwgdXBkYXRlCiAgICAgICAgICAgIC8vCiAgICAgICAgICAgIGlmIChpbml0aWFsVXBkYXRlKSB7CiAgICAgICAgICAgICAgICBFdmVudFF1ZXVlLmludm9rZUxhdGVyKG5ldyBSdW5uYWJsZSgpIHsKICAgICAgICAgICAgICAgICAgICBwdWJsaWMgdm9pZCBydW4oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNlbGVjdCBmaXJzdCBlbmFibGVkIHRhYiBpZiBjdXJyZW50IHRhYiBpc24ndC4KICAgICAgICAgICAgICAgICAgICAgICAgaW50IGluZGV4ID0gZ2V0U2VsZWN0ZWRJbmRleCgpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggPCAwIHx8ICFpc0VuYWJsZWRBdChpbmRleCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRW5hYmxlZEF0KGkpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFNlbGVjdGVkSW5kZXgoaSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgaW5pdGlhbFVwZGF0ZSA9IGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBTdHJpbmcgZ2V0SG9zdE5hbWUoKSB7CiAgICAgICAgcmV0dXJuIGhvc3ROYW1lOwogICAgfQoKICAgIHB1YmxpYyBpbnQgZ2V0UG9ydCgpIHsKICAgICAgICByZXR1cm4gcG9ydDsKICAgIH0KCiAgICBwdWJsaWMgU3RyaW5nIGdldFVzZXJOYW1lKCkgewogICAgICAgIHJldHVybiB1c2VyTmFtZTsKICAgIH0KCiAgICBwdWJsaWMgU3RyaW5nIGdldFVybCgpIHsKICAgICAgICByZXR1cm4gdXJsOwogICAgfQoKCiAgICBwdWJsaWMgU3RyaW5nIGdldFBhc3N3b3JkKCkgewogICAgICAgIHJldHVybiBwYXNzd29yZDsKICAgIH0KCiAgICBwdWJsaWMgU3RyaW5nIGdldENvbm5lY3Rpb25OYW1lKCkgewogICAgICAgIHJldHVybiBwcm94eUNsaWVudC5jb25uZWN0aW9uTmFtZSgpOwogICAgfQoKICAgIHB1YmxpYyBTdHJpbmcgZ2V0RGlzcGxheU5hbWUoKSB7CiAgICAgICAgcmV0dXJuIHByb3h5Q2xpZW50LmdldERpc3BsYXlOYW1lKCk7CiAgICB9CgogICAgc3RhdGljIGNsYXNzIFRhYkluZm8gewogICAgICAgIENsYXNzPD8gZXh0ZW5kcyBUYWI+IHRhYkNsYXNzOwogICAgICAgIFN0cmluZyBuYW1lOwogICAgICAgIGJvb2xlYW4gdGFiVmlzaWJsZTsKCiAgICAgICAgVGFiSW5mbyhDbGFzczw/IGV4dGVuZHMgVGFiPiB0YWJDbGFzcywgU3RyaW5nIG5hbWUsIGJvb2xlYW4gdGFiVmlzaWJsZSkgewogICAgICAgICAgICB0aGlzLnRhYkNsYXNzID0gdGFiQ2xhc3M7CiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgICAgIHRoaXMudGFiVmlzaWJsZSA9IHRhYlZpc2libGU7CiAgICAgICAgfQogICAgfQoKICAgIC8vIENvbnZlbmllbmNlIG1ldGhvZHMKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBnZXRUZXh0KFN0cmluZyBrZXksIE9iamVjdC4uLiBhcmdzKSB7CiAgICAgICAgcmV0dXJuIFJlc291cmNlcy5nZXRUZXh0KGtleSwgYXJncyk7CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIGNyZWF0ZVBsdWdpblRhYnMoKSB7CiAgICAgICAgLy8gYWRkIHBsdWdpbiB0YWJzIGlmIG5vdCBkb25lCiAgICAgICAgaWYgKCFwbHVnaW5UYWJzQWRkZWQpIHsKICAgICAgICAgICAgZm9yIChKQ29uc29sZVBsdWdpbiBwIDogcGx1Z2lucy5rZXlTZXQoKSkgewogICAgICAgICAgICAgICAgTWFwPFN0cmluZywgSlBhbmVsPiB0YWJzID0gcC5nZXRUYWJzKCk7CiAgICAgICAgICAgICAgICBmb3IgKE1hcC5FbnRyeTxTdHJpbmcsIEpQYW5lbD4gZSA6IHRhYnMuZW50cnlTZXQoKSkgewogICAgICAgICAgICAgICAgICAgIGFkZFRhYihlLmdldEtleSgpLCBlLmdldFZhbHVlKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHBsdWdpblRhYnNBZGRlZCA9IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgdm9pZCBmaXJlQ29ubmVjdGVkQ2hhbmdlKGJvb2xlYW4gY29ubmVjdGVkKSB7CiAgICAgICAgZm9yIChUYWIgdGFiIDogZ2V0VGFicygpKSB7CiAgICAgICAgICAgIHRhYi5maXJlUHJvcGVydHlDaGFuZ2UoSkNvbnNvbGVDb250ZXh0LkNPTk5FQ1RJT05fU1RBVEVfUFJPUEVSVFksICFjb25uZWN0ZWQsIGNvbm5lY3RlZCk7CiAgICAgICAgfQogICAgfQp9Cg==