LyoKKiBDb3B5cmlnaHQgqSB7MTk5Ny0xOTk5fSwgSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLiBBbGwgUmlnaHRzIFJlc2VydmVkLgoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqCiogRmlsZSBNU0dGTVQuSAoqCiogTW9kaWZpY2F0aW9uIEhpc3Rvcnk6CioKKiAgIERhdGUgICAgICAgIE5hbWUgICAgICAgIERlc2NyaXB0aW9uCiogICAwMi8xOS85NyAgICBhbGl1ICAgICAgICBDb252ZXJ0ZWQgZnJvbSBqYXZhLgoqICAgMDMvMjAvOTcgICAgaGVsZW5hICAgICAgRmluaXNoZWQgZmlyc3QgY3V0IG9mIGltcGxlbWVudGF0aW9uLgoqICAgIDA3LzIyLzk4ICAgIHN0ZXBoZW4gICAgICAgIFJlbW92ZWQgb3BlcmF0b3IhPSAoZGVmaW5lZCBpbiBGb3JtYXQpCioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiovCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIFRoaXMgZmlsZSB3YXMgZ2VuZXJhdGVkIGZyb20gdGhlIGphdmEgc291cmNlIGZpbGUgTWVzc2FnZUZvcm1hdC5qYXZhCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAKI2lmbmRlZiBNU0dGTVRfSAojZGVmaW5lIE1TR0ZNVF9ICiAKI2luY2x1ZGUgInVuaWNvZGUvdXR5cGVzLmgiCiNpbmNsdWRlICJ1bmljb2RlL2Zvcm1hdC5oIgojaW5jbHVkZSAidW5pY29kZS9sb2NpZC5oIgpjbGFzcyBOdW1iZXJGb3JtYXQ7CgovKioKICogUHJvdmlkZXMgbWVhbnMgdG8gcHJvZHVjZSBjb25jYXRlbmF0ZWQgbWVzc2FnZXMgaW4gbGFuZ3VhZ2UtbmV1dHJhbCB3YXkuCiAqIFVzZSB0aGlzIGZvciBhbGwgY29uY2F0ZW5hdGlvbnMgdGhhdCBzaG93IHVwIHRvIGVuZCB1c2Vycy4KICogPFA+CiAqIFRha2VzIGEgc2V0IG9mIG9iamVjdHMsIGZvcm1hdHMgdGhlbSwgdGhlbiBpbnNlcnRzIHRoZSBmb3JtYXR0ZWQKICogc3RyaW5ncyBpbnRvIHRoZSBwYXR0ZXJuIGF0IHRoZSBhcHByb3ByaWF0ZSBwbGFjZXMuCiAqIDxQPgogKiBIZXJlIGFyZSBzb21lIGV4YW1wbGVzIG9mIHVzYWdlOgogKiBFeGFtcGxlIDE6CiAqIDxwcmU+CiAqIC4gICAgVUVycm9yQ29kZSBzdWNjZXNzID0gVV9aRVJPX0VSUk9SOwogKiAuICAgIEdyZWdvcmlhbkNhbGVuZGFyIGNhbChzdWNjZXNzKTsKICogLiAgICBGb3JtYXR0YWJsZSBhcmd1bWVudHNbXSA9IHsKICogLiAgICAgICAgN0wsCiAqIC4gICAgICAgIEZvcm1hdHRhYmxlKCAoRGF0ZSkgY2FsLmdldFRpbWUoc3VjY2VzcyksIEZvcm1hdHRhYmxlOjprSXNEYXRlKSwKICogLiAgICAgICAgImEgZGlzdHVyYmFuY2UgaW4gdGhlIEZvcmNlIgogKiAuICAgIH07CiAqIC4gICAgCiAqIC4gICAgVW5pY29kZVN0cmluZyByZXN1bHQ7CiAqIC4gICAgTWVzc2FnZUZvcm1hdDo6Zm9ybWF0KAogKiAuICAgICAgICAgIkF0IHsxLHRpbWV9IG9uIHsxLGRhdGV9LCB0aGVyZSB3YXMgezJ9IG9uIHBsYW5ldCB7MCxudW1iZXJ9LiIsCiAqIC4gICAgICAgICBhcmd1bWVudHMsIDMsIHJlc3VsdCwgc3VjY2VzcyApOwogKiAuICAgIAogKiAuICAgIGNvdXQgJmx0OyZsdDsgInJlc3VsdDogIiAmbHQ7Jmx0OyByZXN1bHQgJmx0OyZsdDsgZW5kbDsKICogLiAgICAvLyZsdDtvdXRwdXQ+OiBBdCA0OjM0OjIwIFBNIG9uIDIzLU1hci05OCwgdGhlcmUgd2FzIGEgZGlzdHVyYmFuY2UKICogLiAgICAvLyAgICAgICAgICAgICBpbiB0aGUgRm9yY2Ugb24gcGxhbmV0IDcuCiAqIDwvcHJlPiAgCiAqIFR5cGljYWxseSwgdGhlIG1lc3NhZ2UgZm9ybWF0IHdpbGwgY29tZSBmcm9tIHJlc291cmNlcywgYW5kIHRoZQogKiBhcmd1bWVudHMgd2lsbCBiZSBkeW5hbWljYWxseSBzZXQgYXQgcnVudGltZS4KICogPFA+CiAqIEV4YW1wbGUgMjoKICogPHByZT4KICogLiAgICBzdWNjZXNzID0gVV9aRVJPX0VSUk9SOwogKiAuICAgIEZvcm1hdHRhYmxlIHRlc3RBcmdzW10gPSB7M0wsICJNeURpc2sifTsKICogLiAgIAogKiAuICAgIE1lc3NhZ2VGb3JtYXQqIGZvcm0gPSBuZXcgTWVzc2FnZUZvcm1hdCgKICogLiAgICAgICAgIlRoZSBkaXNrIFwiezF9XCIgY29udGFpbnMgezB9IGZpbGUocykuIiwgc3VjY2VzcyApOwogKiAuICAgICAgICAKICogLiAgICBVbmljb2RlU3RyaW5nIHN0cmluZzsKICogLiAgICBGaWVsZFBvc2l0aW9uIGZwb3MgPSAwOwogKiAuICAgIGNvdXQgJmx0OyZsdDsgImZvcm1hdDogIiAmbHQ7Jmx0OyBmb3JtLT5mb3JtYXQodGVzdEFyZ3MsIDIsIHN0cmluZywgZnBvcywgc3VjY2VzcyApICZsdDsmbHQ7IGVuZGw7CiAqIC4KICogLiAgICAvLyBvdXRwdXQsIHdpdGggZGlmZmVyZW50IHRlc3RBcmdzOgogKiAuICAgIC8vIG91dHB1dDogVGhlIGRpc2sgIk15RGlzayIgY29udGFpbnMgMCBmaWxlKHMpLgogKiAuICAgIC8vIG91dHB1dDogVGhlIGRpc2sgIk15RGlzayIgY29udGFpbnMgMSBmaWxlKHMpLgogKiAuICAgIC8vIG91dHB1dDogVGhlIGRpc2sgIk15RGlzayIgY29udGFpbnMgMSwyNzMgZmlsZShzKS4KICogLiAgICBkZSBsZXRlIGZvcm07CiAqICA8L3ByZT4KICoKICogIFRoZSBwYXR0ZXJuIGlzIG9mIHRoZSBmb2xsb3dpbmcgZm9ybS4gIExlZ2VuZDoKICogIDxwcmU+CiAqIC4gICAgICB7b3B0aW9uYWwgaXRlbX0KICogLiAgICAgIChncm91cCB0aGF0IG1heSBiZSByZXBlYXRlZCkqCiAqICA8L3ByZT4KICogIERvIG5vdCBjb25mdXNlIG9wdGlvbmFsIGl0ZW1zIHdpdGggaXRlbXMgaW5zaWRlIHF1b3RlcyBicmFjZXMsIHN1Y2gKICogIGFzIHRoaXM6ICJ7Ii4gIFF1b3RlZCBicmFjZXMgYXJlIGxpdGVyYWxzLgogKiAgPHByZT4KICogLiAgICAgIG1lc3NhZ2VGb3JtYXRQYXR0ZXJuIDo9IHN0cmluZyAoICJ7IiBtZXNzYWdlRm9ybWF0RWxlbWVudCAifSIgc3RyaW5nICkqCiAqIC4gICAgICAgCiAqIC4gICAgICBtZXNzYWdlRm9ybWF0RWxlbWVudCA6PSBhcmd1bWVudCB7ICIsIiBlbGVtZW50Rm9ybWF0IH0KICogLiAgICAgICAKICogLiAgICAgIGVsZW1lbnRGb3JtYXQgOj0gInRpbWUiIHsgIiwiIGRhdGV0aW1lU3R5bGUgfQogKiAuICAgICAgICAgICAgICAgICAgICAgfCAiZGF0ZSIgeyAiLCIgZGF0ZXRpbWVTdHlsZSB9CiAqIC4gICAgICAgICAgICAgICAgICAgICB8ICJudW1iZXIiIHsgIiwiIG51bWJlclN0eWxlIH0KICogLiAgICAgICAgICAgICAgICAgICAgIHwgImNob2ljZSIgIiwiIGNob2ljZVN0eWxlCiAqIC4gIAogKiAuICAgICAgZGF0ZXRpbWVTdHlsZSA6PSAic2hvcnQiCiAqIC4gICAgICAgICAgICAgICAgICAgICB8ICJtZWRpdW0iCiAqIC4gICAgICAgICAgICAgICAgICAgICB8ICJsb25nIgogKiAuICAgICAgICAgICAgICAgICAgICAgfCAiZnVsbCIKICogLiAgICAgICAgICAgICAgICAgICAgIHwgZGF0ZUZvcm1hdFBhdHRlcm4KICogLgogKiAuICAgICAgbnVtYmVyU3R5bGUgOj0gICAiY3VycmVuY3kiCiAqIC4gICAgICAgICAgICAgICAgICAgICB8ICJwZXJjZW50IgogKiAuICAgICAgICAgICAgICAgICAgICAgfCAiaW50ZWdlciIKICogLiAgICAgICAgICAgICAgICAgICAgIHwgbnVtYmVyRm9ybWF0UGF0dGVybgogKiAuIAogKiAuICAgICAgY2hvaWNlU3R5bGUgOj0gICBjaG9pY2VGb3JtYXRQYXR0ZXJuCiAqIDwvcHJlPgogKiBJZiB0aGVyZSBpcyBubyBlbGVtZW50Rm9ybWF0LCB0aGVuIHRoZSBhcmd1bWVudCBtdXN0IGJlIGEgc3RyaW5nLAogKiB3aGljaCBpcyBzdWJzdGl0dXRlZC4gSWYgdGhlcmUgaXMgbm8gZGF0ZVRpbWVTdHlsZSBvciBudW1iZXJTdHlsZSwKICogdGhlbiB0aGUgZGVmYXVsdCBmb3JtYXQgaXMgdXNlZCAoZS5nLiAgTnVtYmVyRm9ybWF0LmdldEluc3RhbmNlKCksCiAqIERhdGVGb3JtYXQuZ2V0RGVmYXVsdFRpbWUoKSBvciBEYXRlRm9ybWF0LmdldERlZmF1bHREYXRlKCkuIEZvcgogKiBhIENob2ljZUZvcm1hdCwgdGhlIHBhdHRlcm4gbXVzdCBhbHdheXMgYmUgc3BlY2lmaWVkLCBzaW5jZSB0aGVyZQogKiBpcyBubyBkZWZhdWx0LgogKiA8UD4KICogSW4gc3RyaW5ncywgc2luZ2xlIHF1b3RlcyBjYW4gYmUgdXNlZCB0byBxdW90ZSB0aGUgInsiIHNpZ24gaWYKICogbmVjZXNzYXJ5LiBBIHJlYWwgc2luZ2xlIHF1b3RlIGlzIHJlcHJlc2VudGVkIGJ5ICcnLiAgSW5zaWRlIGEKICogbWVzc2FnZUZvcm1hdEVsZW1lbnQsIHF1b3RlcyBhcmUgW25vdF0gcmVtb3ZlZC4gRm9yIGV4YW1wbGUsCiAqIHsxLG51bWJlciwkJyMnLCMjfSB3aWxsIHByb2R1Y2UgYSBudW1iZXIgZm9ybWF0IHdpdGggdGhlIHBvdW5kLXNpZ24KICogcXVvdGVkLCB3aXRoIGEgcmVzdWx0IHN1Y2ggYXM6ICIkIzMxLDQ1Ii4KICogPFA+CiAqIElmIGEgcGF0dGVybiBpcyB1c2VkLCB0aGVuIHVucXVvdGVkIGJyYWNlcyBpbiB0aGUgcGF0dGVybiwgaWYgYW55LAogKiBtdXN0IG1hdGNoOiB0aGF0IGlzLCAiYWIgezB9IGRlIiBhbmQgImFiICd9JyBkZSIgYXJlIG9rLCBidXQgImFiCiAqIHswJ30nIGRlIiBhbmQgImFiIH0gZGUiIGFyZSBub3QuCiAqIDxQPgogKiBUaGUgYXJndW1lbnQgaXMgYSBudW1iZXIgZnJvbSAwIHRvIDksIHdoaWNoIGNvcnJlc3BvbmRzIHRvIHRoZQogKiBhcmd1bWVudHMgcHJlc2VudGVkIGluIGFuIGFycmF5IHRvIGJlIGZvcm1hdHRlZC4KICogPFA+CiAqIEl0IGlzIG9rIHRvIGhhdmUgdW51c2VkIGFyZ3VtZW50cyBpbiB0aGUgYXJyYXkuICBXaXRoIG1pc3NpbmcKICogYXJndW1lbnRzIG9yIGFyZ3VtZW50cyB0aGF0IGFyZSBub3Qgb2YgdGhlIHJpZ2h0IGNsYXNzIGZvciB0aGUKICogc3BlY2lmaWVkIGZvcm1hdCwgYSBmYWlsaW5nIFVFcnJvckNvZGUgcmVzdWx0IGlzIHNldC4KICogPFA+CiAqIEZvciBtb3JlIHNvcGhpc3RpY2F0ZWQgcGF0dGVybnMsIHlvdSBjYW4gdXNlIGEgQ2hvaWNlRm9ybWF0IHRvIGdldAogKiBvdXRwdXQgc3VjaCBhczoKICogPHByZT4KICogLiAgICBVRXJyb3JDb2RlIHN1Y2Nlc3MgPSBVX1pFUk9fRVJST1I7CiAqIC4gICAgTWVzc2FnZUZvcm1hdCogZm9ybSA9IG5ldyBNZXNzYWdlRm9ybWF0KCJUaGUgZGlzayBcInsxfVwiIGNvbnRhaW5zIHswfS4iLCBzdWNjZXNzKTsKICogLiAgICBkb3VibGUgZmlsZWxpbWl0c1tdID0gezAsMSwyfTsKICogLiAgICBVbmljb2RlU3RyaW5nIGZpbGVwYXJ0W10gPSB7Im5vIGZpbGVzIiwib25lIGZpbGUiLCJ7MCxudW1iZXJ9IGZpbGVzIn07CiAqIC4gICAgQ2hvaWNlRm9ybWF0KiBmaWxlZm9ybSA9IG5ldyBDaG9pY2VGb3JtYXQoZmlsZWxpbWl0cywgZmlsZXBhcnQsIDMpOwogKiAuICAgIGZvcm0tPnNldEZvcm1hdCgxLCAqZmlsZWZvcm0pOyAvLyBOT1QgemVybywgc2VlIGJlbG93CiAqIC4gICAgCiAqIC4gICAgRm9ybWF0dGFibGUgdGVzdEFyZ3NbXSA9IHsxMjczTCwgIk15RGlzayJ9OwogKiAuICAgICAKICogLiAgICBVbmljb2RlU3RyaW5nIHN0cmluZzsKICogLiAgICBGaWVsZFBvc2l0aW9uIGZwb3MgPSAwOwogKiAuICAgIGNvdXQgJmx0OyZsdDsgZm9ybS0+Zm9ybWF0KHRlc3RBcmdzLCAyLCBzdHJpbmcsIGZwb3MsIHN1Y2Nlc3MpICZsdDsmbHQ7IGVuZGw7CiAqIC4gICAgCiAqIC4gICAgLy8gb3V0cHV0LCB3aXRoIGRpZmZlcmVudCB0ZXN0QXJncwogKiAuICAgIC8vIG91dHB1dDogVGhlIGRpc2sgIk15RGlzayIgY29udGFpbnMgbm8gZmlsZXMuCiAqIC4gICAgLy8gb3V0cHV0OiBUaGUgZGlzayAiTXlEaXNrIiBjb250YWlucyBvbmUgZmlsZS4KICogLiAgICAvLyBvdXRwdXQ6IFRoZSBkaXNrICJNeURpc2siIGNvbnRhaW5zIDEsMjczIGZpbGVzLgogKiA8L3ByZT4KICogWW91IGNhbiBlaXRoZXIgZG8gdGhpcyBwcm9ncmFtbWF0aWNhbGx5LCBhcyBpbiB0aGUgYWJvdmUgZXhhbXBsZSwKICogb3IgYnkgdXNpbmcgYSBwYXR0ZXJuIChzZWUgQ2hvaWNlRm9ybWF0IGZvciBtb3JlIGluZm9ybWF0aW9uKSBhcyBpbjoKICogPHByZT4KICogLiAgIGZvcm0tPmFwcGx5UGF0dGVybigKICogLiAgICAgIlRoZXJlIHswLGNob2ljZSwwI2FyZSBubyBmaWxlc3wxI2lzIG9uZSBmaWxlfDEmbHQ7YXJlIHswLG51bWJlcixpbnRlZ2VyfSBmaWxlc30uIik7CiAqIDwvcHJlPgogKiA8UD4KICogW05vdGU6XSBBcyB3ZSBzZWUgYWJvdmUsIHRoZSBzdHJpbmcgcHJvZHVjZWQgYnkgYSBDaG9pY2VGb3JtYXQgaW4KICogTWVzc2FnZUZvcm1hdCBpcyB0cmVhdGVkIHNwZWNpYWxseTsgb2NjdXJhbmNlcyBvZiAneycgYXJlIHVzZWQgdG8KICogaW5kaWNhdGVkIHN1YmZvcm1hdHMsIGFuZCBjYXVzZSByZWN1cnNpb24uICBJZiB5b3UgY3JlYXRlIGJvdGggYQogKiBNZXNzYWdlRm9ybWF0IGFuZCBDaG9pY2VGb3JtYXQgcHJvZ3JhbW1hdGljYWxseSAoaW5zdGVhZCBvZiB1c2luZwogKiB0aGUgc3RyaW5nIHBhdHRlcm5zKSwgdGhlbiBiZSBjYXJlZnVsIG5vdCB0byBwcm9kdWNlIGEgZm9ybWF0IHRoYXQKICogcmVjdXJzZXMgb24gaXRzZWxmLCB3aGljaCB3aWxsIGNhdXNlIGFuIGluZmluaXRlIGxvb3AuCiAqIDxQPgogKiBbTm90ZTpdIEZvcm1hdHMgYXJlIG51bWJlcmVkIGJ5IG9yZGVyIG9mIHZhcmlhYmxlIGluIHRoZSBzdHJpbmcuCiAqIFRoaXMgaXMgW25vdF0gdGhlIHNhbWUgYXMgdGhlIGFyZ3VtZW50IG51bWJlcmluZyEKICogPHByZT4KICogLiAgIEZvciBleGFtcGxlOiB3aXRoICJhYmN7Mn1kZWZ7M31naGl7MH0uLi4iLAogKiAuICAgCiAqIC4gICBmb3JtYXQwIGFmZmVjdHMgdGhlIGZpcnN0IHZhcmlhYmxlIHsyfQogKiAuICAgZm9ybWF0MSBhZmZlY3RzIHRoZSBzZWNvbmQgdmFyaWFibGUgezN9CiAqIC4gICBmb3JtYXQyIGFmZmVjdHMgdGhlIHNlY29uZCB2YXJpYWJsZSB7MH0KICogPC9wcmU+CiAqIGFuZCBzbyBvbi4KICovCmNsYXNzIFVfSTE4Tl9BUEkgTWVzc2FnZUZvcm1hdCA6IHB1YmxpYyBGb3JtYXQgewpwdWJsaWM6CiAgICBlbnVtIEVGb3JtYXROdW1iZXIgeyBrTWF4Rm9ybWF0ID0gMTAgfTsKICAgIC8qKgogICAgICogQ29uc3RydWN0IGEgbmV3IE1lc3NhZ2VGb3JtYXQgdXNpbmcgdGhlIGdpdmVuIHBhdHRlcm4uCiAgICAgKgogICAgICogQHBhcmFtIHBhdHRlcm4gICBQYXR0ZXJuIHVzZWQgdG8gY29uc3RydWN0IG9iamVjdC4KICAgICAqIEBwYXJhbSBzdGF0dXMgICAgT3V0cHV0IHBhcmFtIHRvIHJlY2VpdmUgc3VjY2VzcyBjb2RlLiAgSWYgdGhlCiAgICAgKiAgICAgICAgICAgICAgICAgIHBhdHRlcm4gY2Fubm90IGJlIHBhcnNlZCwgc2V0IHRvIGZhaWx1cmUgY29kZS4KICAgICAqLwogICAgTWVzc2FnZUZvcm1hdChjb25zdCBVbmljb2RlU3RyaW5nJiBwYXR0ZXJuLAogICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlICZzdGF0dXMpOwoKICAgIC8qKgogICAgICogQ29uc3RydWN0b3IgdGhhdCBhbGxvd3MgbG9jYWxlIHNwZWNpZmljYXRpb24uCiAgICAgKiBAcGFyYW0gcGF0dGVybiAgIFBhdHRlcm4gdXNlZCB0byBjb25zdHJ1Y3Qgb2JqZWN0LgogICAgICogQHBhcmFtIG5ld0xvY2FsZSBUaGUgbG9jYWxlIHRvIHVzZSBmb3IgZm9ybWF0dGluZyBkYXRlcyBhbmQgbnVtYmVycy4KICAgICAqIEBwYXJhbSBzdGF0dXMgICAgT3V0cHV0IHBhcmFtIHRvIHJlY2VpdmUgc3VjY2VzcyBjb2RlLiAgSWYgdGhlCiAgICAgKiAgICAgICAgICAgICAgICAgIHBhdHRlcm4gY2Fubm90IGJlIHBhcnNlZCwgc2V0IHRvIGZhaWx1cmUgY29kZS4KICAgICAqLwogICAgTWVzc2FnZUZvcm1hdChjb25zdCBVbmljb2RlU3RyaW5nJiBwYXR0ZXJuLAogICAgICAgICAgICAgICAgICBjb25zdCBMb2NhbGUmIG5ld0xvY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3VjY2Vzcyk7CgogICAgLyoqCiAgICAgKiBDb3B5IGNvbnN0cnVjdG9yLgogICAgICovCiAgICBNZXNzYWdlRm9ybWF0KGNvbnN0IE1lc3NhZ2VGb3JtYXQmKTsKCiAgICAvKioKICAgICAqIEFzc2lnbm1lbnQgb3BlcmF0b3IuCiAgICAgKi8KICAgIGNvbnN0IE1lc3NhZ2VGb3JtYXQmIG9wZXJhdG9yPShjb25zdCBNZXNzYWdlRm9ybWF0Jik7CgogICAgLyoqCiAgICAgKiBEZXN0cnVjdG9yLgogICAgICovCiAgICB2aXJ0dWFsIH5NZXNzYWdlRm9ybWF0KCk7CgogICAgLyoqCiAgICAgKiBDbG9uZSB0aGlzIEZvcm1hdCBvYmplY3QgcG9seW1vcnBoaWNhbGx5LiBUaGUgY2FsbGVyIG93bnMgdGhlCiAgICAgKiByZXN1bHQgYW5kIHNob3VsZCBkZWxldGUgaXQgd2hlbiBkb25lLgogICAgICovCiAgICB2aXJ0dWFsIEZvcm1hdCogY2xvbmUodm9pZCkgY29uc3Q7CgogICAgLyoqCiAgICAgKiBSZXR1cm4gdHJ1ZSBpZiB0aGUgZ2l2ZW4gRm9ybWF0IG9iamVjdHMgYXJlIHNlbWFudGljYWxseSBlcXVhbC4KICAgICAqIE9iamVjdHMgb2YgZGlmZmVyZW50IHN1YmNsYXNzZXMgYXJlIGNvbnNpZGVyZWQgdW5lcXVhbC4KICAgICAqLwogICAgdmlydHVhbCBib29sX3Qgb3BlcmF0b3I9PShjb25zdCBGb3JtYXQmIG90aGVyKSBjb25zdDsKCiAgICAvKioKICAgICAqIFNldHMgdGhlIGxvY2FsZS4gVGhpcyBsb2NhbGUgaXMgdXNlZCBmb3IgZmV0Y2hpbmcgZGVmYXVsdCBudW1iZXIgb3IgZGF0ZQogICAgICogZm9ybWF0IGluZm9ybWF0aW9uLgogICAgICovCiAgICB2aXJ0dWFsIHZvaWQgc2V0TG9jYWxlKGNvbnN0IExvY2FsZSYgdGhlTG9jYWxlKTsKCiAgICAvKioKICAgICAqIEdldHMgdGhlIGxvY2FsZS4gVGhpcyBsb2NhbGUgaXMgdXNlZCBmb3IgZmV0Y2hpbmcgZGVmYXVsdCBudW1iZXIgb3IgZGF0ZQogICAgICogZm9ybWF0IGluZm9ybWF0aW9uLgogICAgICovCiAgICB2aXJ0dWFsIGNvbnN0IExvY2FsZSYgZ2V0TG9jYWxlKHZvaWQpIGNvbnN0OwoKICAgIC8qKgogICAgICogQXBwbHkgdGhlIGdpdmVuIHBhdHRlcm4gc3RyaW5nIHRvIHRoaXMgbWVzc2FnZSBmb3JtYXQuCiAgICAgKgogICAgICogQHBhcmFtIHBhdHRlcm4gICBUaGUgcGF0dGVybiB0byBiZSBhcHBsaWVkLgogICAgICogQHBhcmFtIHN0YXR1cyAgICBPdXRwdXQgcGFyYW0gc2V0IHRvIHN1Y2Nlc3MvZmFpbHVyZSBjb2RlIG9uCiAgICAgKiAgICAgICAgICAgICAgICAgIGV4aXQuIElmIHRoZSBwYXR0ZXJuIGlzIGludmFsaWQsIHRoaXMgd2lsbCBiZQogICAgICogICAgICAgICAgICAgICAgICBzZXQgdG8gYSBmYWlsdXJlIHJlc3VsdC4KICAgICAqLwogICAgdmlydHVhbCB2b2lkIGFwcGx5UGF0dGVybihjb25zdCBVbmljb2RlU3RyaW5nJiBwYXR0ZXJuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpOwoKICAgIC8qKgogICAgICogR2V0cyB0aGUgcGF0dGVybi4gU2VlIHRoZSBjbGFzcyBkZXNjcmlwdGlvbi4KICAgICAqLwogICAgdmlydHVhbCBVbmljb2RlU3RyaW5nJiB0b1BhdHRlcm4oVW5pY29kZVN0cmluZyYgcmVzdWx0KSBjb25zdDsKCiAgICAvKioKICAgICAqIFNldHMgZm9ybWF0cyB0byB1c2Ugb24gcGFyYW1ldGVycy4KICAgICAqIFNlZSB0aGUgY2xhc3MgZGVzY3JpcHRpb24gYWJvdXQgZm9ybWF0IG51bWJlcmluZy4KICAgICAqIFRoZSBjYWxsZXIgc2hvdWxkIG5vdCBkZWxldGUgdGhlIEZvcm1hdCBvYmplY3RzIGFmdGVyIHRoaXMgY2FsbC4KICAgICAqLwogICAgdmlydHVhbCB2b2lkIGFkb3B0Rm9ybWF0cyhGb3JtYXQqKiBmb3JtYXRzVG9BZG9wdCwgaW50MzJfdCBjb3VudCk7CgogICAgLyoqCiAgICAgKiBTZXRzIGZvcm1hdHMgdG8gdXNlIG9uIHBhcmFtZXRlcnMuCiAgICAgKiBTZWUgdGhlIGNsYXNzIGRlc2NyaXB0aW9uIGFib3V0IGZvcm1hdCBudW1iZXJpbmcuCiAgICAgKi8KICAgIHZpcnR1YWwgdm9pZCBzZXRGb3JtYXRzKGNvbnN0IEZvcm1hdCoqIG5ld0Zvcm1hdHMsaW50MzJfdCBjbnQpOwoKCiAgICAvKioKICAgICAqIFNldHMgZm9ybWF0cyBpbmRpdmlkdWFsbHkgdG8gdXNlIG9uIHBhcmFtZXRlcnMuCiAgICAgKiBTZWUgdGhlIGNsYXNzIGRlc2NyaXB0aW9uIGFib3V0IGZvcm1hdCBudW1iZXJpbmcuCiAgICAgKiBUaGUgY2FsbGVyIHNob3VsZCBub3QgZGVsZXRlIHRoZSBGb3JtYXQgb2JqZWN0IGFmdGVyIHRoaXMgY2FsbC4KICAgICAqLwogICAgdmlydHVhbCB2b2lkIGFkb3B0Rm9ybWF0KGludDMyX3QgZm9ybWF0TnVtYmVyLCBGb3JtYXQqIGZvcm1hdFRvQWRvcHQpOwoKICAgIC8qKgogICAgICogU2V0cyBmb3JtYXRzIGluZGl2aWR1YWxseSB0byB1c2Ugb24gcGFyYW1ldGVycy4KICAgICAqIFNlZSB0aGUgY2xhc3MgZGVzY3JpcHRpb24gYWJvdXQgZm9ybWF0IG51bWJlcmluZy4KICAgICAqLwogICAgdmlydHVhbCB2b2lkIHNldEZvcm1hdChpbnQzMl90IHZhcmlhYmxlLCBjb25zdCBGb3JtYXQmIG5ld0Zvcm1hdCk7CgoKICAgIC8qKgogICAgICogR2V0cyBmb3JtYXRzIHRoYXQgd2VyZSBzZXQgd2l0aCBzZXRGb3JtYXRzLgogICAgICogU2VlIHRoZSBjbGFzcyBkZXNjcmlwdGlvbiBhYm91dCBmb3JtYXQgbnVtYmVyaW5nLgogICAgICovCiAgICB2aXJ0dWFsIGNvbnN0IEZvcm1hdCoqIGdldEZvcm1hdHMoaW50MzJfdCYgY291bnQpIGNvbnN0OwoKICAgIC8qKgogICAgICogUmV0dXJucyBwYXR0ZXJuIHdpdGggZm9ybWF0dGVkIG9iamVjdHMuICBEb2VzIG5vdCB0YWtlIG93bmVyc2hpcAogICAgICogb2YgdGhlIEZvcm1hdHRhYmxlKiBhcnJheTsganVzdCByZWFkcyBpdCBhbmQgdXNlcyBpdCB0byBnZW5lcmF0ZQogICAgICogdGhlIGZvcm1hdCBzdHJpbmcuCiAgICAgKgogICAgICogQHBhcmFtIHNvdXJjZSAgICBBbiBhcnJheSBvZiBvYmplY3RzIHRvIGJlIGZvcm1hdHRlZCAmIHN1YnN0aXR1dGVkLgogICAgICogQHBhcmFtIHJlc3VsdCAgICBXaGVyZSB0ZXh0IGlzIGFwcGVuZGVkLgogICAgICogQHBhcmFtIGlnbm9yZSAgICBObyB1c2VmdWwgc3RhdHVzIGlzIHJldHVybmVkLgogICAgICovCiAgICBVbmljb2RlU3RyaW5nJiBmb3JtYXQoICBjb25zdCBGb3JtYXR0YWJsZSogc291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50MzJfdCBjb3VudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVuaWNvZGVTdHJpbmcmIHJlc3VsdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZpZWxkUG9zaXRpb24mIGlnbm9yZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN1Y2Nlc3MpIGNvbnN0OwoKICAgIC8qKgogICAgICogQ29udmVuaWVuY2Ugcm91dGluZS4gIEF2b2lkcyBleHBsaWNpdCBjcmVhdGlvbiBvZgogICAgICogTWVzc2FnZUZvcm1hdCwgYnV0IGRvZXNuJ3QgYWxsb3cgZnV0dXJlIG9wdGltaXphdGlvbnMuCiAgICAgKi8KICAgIHN0YXRpYyBVbmljb2RlU3RyaW5nJiBmb3JtYXQoICAgY29uc3QgVW5pY29kZVN0cmluZyYgcGF0dGVybiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgRm9ybWF0dGFibGUqIGFyZ3VtZW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50MzJfdCBjb3VudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVW5pY29kZVN0cmluZyYgcmVzdWx0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3VjY2Vzcyk7CgogICAgLyoqCiAgICAgKiBGb3JtYXQgYW4gb2JqZWN0IHRvIHByb2R1Y2UgYSBtZXNzYWdlLiAgVGhpcyBtZXRob2QgaGFuZGxlcwogICAgICogRm9ybWF0dGFibGUgb2JqZWN0cyBvZiB0eXBlIGtBcnJheS4gSWYgdGhlIEZvcm1hdHRhYmxlCiAgICAgKiBvYmplY3QgdHlwZSBpcyBub3Qgb2YgdHlwZSBrQXJyYXksIHRoZW4gaXQgcmV0dXJucyBhIGZhaWxpbmcKICAgICAqIFVFcnJvckNvZGUuCiAgICAgKgogICAgICogQHBhcmFtIG9iaiAgICAgICAgICAgVGhlIG9iamVjdCB0byBmb3JtYXQKICAgICAqIEBwYXJhbSB0b0FwcGVuZFRvICAgIFdoZXJlIHRoZSB0ZXh0IGlzIHRvIGJlIGFwcGVuZGVkCiAgICAgKiBAcGFyYW0gcG9zICAgICAgICAgICBPbiBpbnB1dDogYW4gYWxpZ25tZW50IGZpZWxkLCBpZiBkZXNpcmVkLgogICAgICogICAgICAgICAgICAgICAgICAgICAgT24gb3V0cHV0OiB0aGUgb2Zmc2V0cyBvZiB0aGUgYWxpZ25tZW50IGZpZWxkLgogICAgICogQHBhcmFtIHN0YXR1cyAgICAgICAgT3V0cHV0IHBhcmFtIGZpbGxlZCB3aXRoIHN1Y2Nlc3MvZmFpbHVyZSBzdGF0dXMuCiAgICAgKiBAcmV0dXJuICAgICAgICAgICAgICBUaGUgdmFsdWUgcGFzc2VkIGluIGFzIHRvQXBwZW5kVG8gKHRoaXMgYWxsb3dzIGNoYWluaW5nLAogICAgICogICAgICAgICAgICAgICAgICAgICAgYXMgd2l0aCBVbmljb2RlU3RyaW5nOjphcHBlbmQoKSkKICAgICAqLwogICAgdmlydHVhbCBVbmljb2RlU3RyaW5nJiBmb3JtYXQoY29uc3QgRm9ybWF0dGFibGUmIG9iaiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVuaWNvZGVTdHJpbmcmIHRvQXBwZW5kVG8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGaWVsZFBvc2l0aW9uJiBwb3MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIGNvbnN0OwoKICAgIC8qKgogICAgICogUmVkZWNsYXJlZCBGb3JtYXQgbWV0aG9kLgogICAgICovCiAgICBVbmljb2RlU3RyaW5nJiBmb3JtYXQoY29uc3QgRm9ybWF0dGFibGUmIG9iaiwKICAgICAgICAgICAgICAgICAgICAgICAgICBVbmljb2RlU3RyaW5nJiByZXN1bHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKSBjb25zdDsKCiAgICAvKioKICAgICAqIFBhcnNlcyB0aGUgc3RyaW5nLgogICAgICogPFA+CiAgICAgKiBDYXZlYXRzOiBUaGUgcGFyc2UgbWF5IGZhaWwgaW4gYSBudW1iZXIgb2YgY2lyY3Vtc3RhbmNlcy4gIEZvcgogICAgICogZXhhbXBsZToKICAgICAqIDxQPgogICAgICogSWYgb25lIG9mIHRoZSBhcmd1bWVudHMgZG9lcyBub3Qgb2NjdXIgaW4gdGhlIHBhdHRlcm4uCiAgICAgKiA8UD4KICAgICAqIElmIHRoZSBmb3JtYXQgb2YgYW4gYXJndW1lbnQgaXMgbG9zZXMgaW5mb3JtYXRpb24sIHN1Y2ggYXMgd2l0aAogICAgICogYSBjaG9pY2UgZm9ybWF0IHdoZXJlIGEgbGFyZ2UgbnVtYmVyIGZvcm1hdHMgdG8gIm1hbnkiLgogICAgICogPFA+CiAgICAgKiBEb2VzIG5vdCB5ZXQgaGFuZGxlIHJlY3Vyc2lvbiAod2hlcmUgdGhlIHN1YnN0aXR1dGVkIHN0cmluZ3MKICAgICAqIGNvbnRhaW4ge259IHJlZmVyZW5jZXMuKQogICAgICogPFA+CiAgICAgKiBXaWxsIG5vdCBhbHdheXMgZmluZCBhIG1hdGNoIChvciB0aGUgY29ycmVjdCBtYXRjaCkgaWYgc29tZQogICAgICogcGFydCBvZiB0aGUgcGFyc2UgaXMgYW1iaWd1b3VzLiAgRm9yIGV4YW1wbGUsIGlmIHRoZSBwYXR0ZXJuCiAgICAgKiAiezF9LHsyfSIgaXMgdXNlZCB3aXRoIHRoZSBzdHJpbmcgYXJndW1lbnRzIHsiYSxiIiwgImMifSwgaXQKICAgICAqIHdpbGwgZm9ybWF0IGFzICJhLGIsYyIuICBXaGVuIHRoZSByZXN1bHQgaXMgcGFyc2VkLCBpdCB3aWxsCiAgICAgKiByZXR1cm4geyJhIiwgImIsYyJ9LgogICAgICogPFA+CiAgICAgKiBJZiBhIHNpbmdsZSBhcmd1bWVudCBpcyBmb3JtYXR0ZWQgdHdpY2UgaW4gdGhlIHN0cmluZywgdGhlbiB0aGUKICAgICAqIGxhdGVyIHBhcnNlIHdpbnMuCiAgICAgKgogICAgICogQHBhcmFtIHNvdXJjZSAgICBTdHJpbmcgdG8gYmUgcGFyc2VkLgogICAgICogQHBhcmFtIHN0YXR1cyAgICBPbiBpbnB1dCwgc3RhcnRpbmcgcG9zaXRpb24gZm9yIHBhcnNlLiBPbiBvdXRwdXQsCiAgICAgKiAgICAgICAgICAgICAgICAgIGZpbmFsIHBvc2l0aW9uIGFmdGVyIHBhcnNlLgogICAgICogQHBhcmFtIGNvdW50ICAgICBPdXRwdXQgcGFyYW0gdG8gcmVjZWl2ZSBzaXplIG9mIHJldHVybmVkIGFycmF5LgogICAgICogQHJlc3VsdCAgICAgICAgICBBcnJheSBvZiBGb3JtYXR0YWJsZSBvYmplY3RzLCB3aXRoIGxlbmd0aAogICAgICogICAgICAgICAgICAgICAgICAnY291bnQnLCBvd25lZCBieSB0aGUgY2FsbGVyLgogICAgICovCiAgICB2aXJ0dWFsIEZvcm1hdHRhYmxlKiBwYXJzZSggY29uc3QgVW5pY29kZVN0cmluZyYgc291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBhcnNlUG9zaXRpb24mIHN0YXR1cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90JiBjb3VudCkgY29uc3Q7CgogICAgLyoqCiAgICAgKiBQYXJzZXMgdGhlIHN0cmluZy4gRG9lcyBub3QgeWV0IGhhbmRsZSByZWN1cnNpb24gKHdoZXJlCiAgICAgKiB0aGUgc3Vic3RpdHV0ZWQgc3RyaW5ncyBjb250YWluIHtufSByZWZlcmVuY2VzLikKICAgICAqCiAgICAgKiBAcGFyYW0gc291cmNlICAgIFN0cmluZyB0byBiZSBwYXJzZWQuCiAgICAgKiBAcGFyYW0gY291bnQgICAgIE91dHB1dCBwYXJhbSB0byByZWNlaXZlIHNpemUgb2YgcmV0dXJuZWQgYXJyYXkuCiAgICAgKiBAcGFyYW0gc3RhdHVzICAgIE91dHB1dCBwYXJhbSB0byByZWNlaXZlIHN1Y2Nlc3MvZXJyb3IgY29kZS4KICAgICAqIEByZXN1bHQgICAgICAgICAgQXJyYXkgb2YgRm9ybWF0dGFibGUgb2JqZWN0cywgd2l0aCBsZW5ndGgKICAgICAqICAgICAgICAgICAgICAgICAgJ2NvdW50Jywgb3duZWQgYnkgdGhlIGNhbGxlci4KICAgICAqLwogICAgdmlydHVhbCBGb3JtYXR0YWJsZSogcGFyc2UoIGNvbnN0IFVuaWNvZGVTdHJpbmcmIHNvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90JiBjb3VudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIGNvbnN0OwoKICAgIC8qKgogICAgICogUGFyc2UgYSBzdHJpbmcgdG8gcHJvZHVjZSBhbiBvYmplY3QuICBUaGlzIG1ldGhvZHMgaGFuZGxlcwogICAgICogcGFyc2luZyBvZiBtZXNzYWdlIHN0cmluZ3MgaW50byBhcnJheXMgb2YgRm9ybWF0dGFibGUgb2JqZWN0cy4KICAgICAqIERvZXMgbm90IHlldCBoYW5kbGUgcmVjdXJzaW9uICh3aGVyZSB0aGUgc3Vic3RpdHV0ZWQgc3RyaW5ncwogICAgICogY29udGFpbiAlbiByZWZlcmVuY2VzLikKICAgICAqIDxQPgogICAgICogQmVmb3JlIGNhbGxpbmcsIHNldCBwYXJzZV9wb3MuaW5kZXggdG8gdGhlIG9mZnNldCB5b3Ugd2FudCB0bwogICAgICogc3RhcnQgcGFyc2luZyBhdCBpbiB0aGUgc291cmNlLiBBZnRlciBjYWxsaW5nLCBwYXJzZV9wb3MuaW5kZXgKICAgICAqIGlzIHRoZSBlbmQgb2YgdGhlIHRleHQgeW91IHBhcnNlZC4gIElmIGVycm9yIG9jY3VycywgaW5kZXggaXMKICAgICAqIHVuY2hhbmdlZC4KICAgICAqIDxQPgogICAgICogV2hlbiBwYXJzaW5nLCBsZWFkaW5nIHdoaXRlc3BhY2UgaXMgZGlzY2FyZGVkICh3aXRoIHN1Y2Nlc3NmdWwKICAgICAqIHBhcnNlKSwgd2hpbGUgdHJhaWxpbmcgd2hpdGVzcGFjZSBpcyBsZWZ0IGFzIGlzLgogICAgICogPFA+CiAgICAgKiBTZWUgRm9ybWF0OjpwYXJzZU9iamVjdCgpIGZvciBtb3JlLgogICAgICoKICAgICAqIEBwYXJhbSBzb3VyY2UgICAgVGhlIHN0cmluZyB0byBiZSBwYXJzZWQgaW50byBhbiBvYmplY3QuCiAgICAgKiBAcGFyYW0gcmVzdWx0ICAgIEZvcm1hdHRhYmxlIHRvIGJlIHNldCB0byB0aGUgcGFyc2UgcmVzdWx0LgogICAgICogICAgICAgICAgICAgICAgICBJZiBwYXJzZSBmYWlscywgcmV0dXJuIGNvbnRlbnRzIGFyZSB1bmRlZmluZWQuCiAgICAgKiBAcGFyYW0gcGFyc2VfcG9zIFRoZSBwb3NpdGlvbiB0byBzdGFydCBwYXJzaW5nIGF0LiBVcG9uIHJldHVybgogICAgICogICAgICAgICAgICAgICAgICB0aGlzIHBhcmFtIGlzIHNldCB0byB0aGUgcG9zaXRpb24gYWZ0ZXIgdGhlCiAgICAgKiAgICAgICAgICAgICAgICAgIGxhc3QgY2hhcmFjdGVyIHN1Y2Nlc3NmdWxseSBwYXJzZWQuIElmIHRoZQogICAgICogICAgICAgICAgICAgICAgICBzb3VyY2UgaXMgbm90IHBhcnNlZCBzdWNjZXNzZnVsbHksIHRoaXMgcGFyYW0KICAgICAqICAgICAgICAgICAgICAgICAgd2lsbCByZW1haW4gdW5jaGFuZ2VkLgogICAgICogQHJldHVybiAgICAgICAgICBBIG5ld2x5IGNyZWF0ZWQgRm9ybWF0dGFibGUqIG9iamVjdCwgb3IgTlVMTAogICAgICogICAgICAgICAgICAgICAgICBvbiBmYWlsdXJlLiAgVGhlIGNhbGxlciBvd25zIHRoaXMgYW5kIHNob3VsZAogICAgICogICAgICAgICAgICAgICAgICBkZWxldGUgaXQgd2hlbiBkb25lLgogICAgICovCiAgICB2aXJ0dWFsIHZvaWQgcGFyc2VPYmplY3QoY29uc3QgVW5pY29kZVN0cmluZyYgc291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hdHRhYmxlJiByZXN1bHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGFyc2VQb3NpdGlvbiYgcGFyc2VfcG9zKSBjb25zdDsKCnB1YmxpYzoKICAgIC8qKgogICAgICogUmV0dXJucyBhIHVuaXF1ZSBjbGFzcyBJRCBQT0xZTU9SUEhJQ0FMTFkuICBQdXJlIHZpcnR1YWwgb3ZlcnJpZGUuCiAgICAgKiBUaGlzIG1ldGhvZCBpcyB0byBpbXBsZW1lbnQgYSBzaW1wbGUgdmVyc2lvbiBvZiBSVFRJLCBzaW5jZSBub3QgYWxsCiAgICAgKiBDKysgY29tcGlsZXJzIHN1cHBvcnQgZ2VudWluZSBSVFRJLiAgUG9seW1vcnBoaWMgb3BlcmF0b3I9PSgpIGFuZAogICAgICogY2xvbmUoKSBtZXRob2RzIGNhbGwgdGhpcyBtZXRob2QuCiAgICAgKgogICAgICogQHJldHVybiAgICAgICAgICBUaGUgY2xhc3MgSUQgZm9yIHRoaXMgb2JqZWN0LiBBbGwgb2JqZWN0cyBvZiBhCiAgICAgKiAgICAgICAgICAgICAgICAgIGdpdmVuIGNsYXNzIGhhdmUgdGhlIHNhbWUgY2xhc3MgSUQuICBPYmplY3RzIG9mCiAgICAgKiAgICAgICAgICAgICAgICAgIG90aGVyIGNsYXNzZXMgaGF2ZSBkaWZmZXJlbnQgY2xhc3MgSURzLgogICAgICovCiAgICB2aXJ0dWFsIFVDbGFzc0lEIGdldER5bmFtaWNDbGFzc0lEKHZvaWQpIGNvbnN0OwoKICAgIC8qKgogICAgICogUmV0dXJuIHRoZSBjbGFzcyBJRCBmb3IgdGhpcyBjbGFzcy4gIFRoaXMgaXMgdXNlZnVsIG9ubHkgZm9yCiAgICAgKiBjb21wYXJpbmcgdG8gYSByZXR1cm4gdmFsdWUgZnJvbSBnZXREeW5hbWljQ2xhc3NJRCgpLiAgRm9yIGV4YW1wbGU6CiAgICAgKiA8cHJlPgogICAgICogLiAgIEJhc2UqIHBvbHltb3JwaGljX3BvaW50ZXIgPSBjcmVhdGVQb2x5bW9ycGhpY09iamVjdCgpOwogICAgICogLiAgIGlmIChwb2x5bW9ycGhpY19wb2ludGVyLT5nZXREeW5hbWljQ2xhc3NJRCgpID09CiAgICAgKiAuICAgICAgRGVyaXZlZDo6Z2V0U3RhdGljQ2xhc3NJRCgpKSAuLi4KICAgICAqIDwvcHJlPgogICAgICogQHJldHVybiAgICAgICAgICBUaGUgY2xhc3MgSUQgZm9yIGFsbCBvYmplY3RzIG9mIHRoaXMgY2xhc3MuCiAgICAgKi8KICAgIHN0YXRpYyBVQ2xhc3NJRCBnZXRTdGF0aWNDbGFzc0lEKHZvaWQpIHsgcmV0dXJuIChVQ2xhc3NJRCkmZmdDbGFzc0lEOyB9Cgpwcml2YXRlOgogICAgc3RhdGljIGNoYXIgZmdDbGFzc0lEOwogICAgc3RhdGljIE51bWJlckZvcm1hdCogZmdOdW1iZXJGb3JtYXQ7CgogICAgLy8gZmdOdW1iZXJGb3JtYXQgaXMgaGVsZCBpbiBhIGNhY2hlIG9mIG9uZS4KCiAgICBzdGF0aWMgTnVtYmVyRm9ybWF0KiBnZXROdW1iZXJGb3JtYXQoVUVycm9yQ29kZSAmc3RhdHVzKTsgLy8gY2FsbCB0aGlzIGZ1bmN0aW9uIHRvICdjaGVjayBvdXQnIGEgbnVtYmVyZm9ybWF0IGZyb20gdGhlIGNhY2hlLgogICAgc3RhdGljIHZvaWQgICAgICAgICAgcmVsZWFzZU51bWJlckZvcm1hdChOdW1iZXJGb3JtYXQgKmFkb3B0KTsgLy8gY2FsbCB0aGlzIGZ1bmN0aW9uIHRvICdyZXR1cm4nIHRoZSBudW1iZXIgZm9ybWF0IHRvIHRoZSBjYWNoZS4KCiAgICBMb2NhbGUgICAgICAgICAgICAgICAgIGZMb2NhbGU7CiAgICBVbmljb2RlU3RyaW5nICAgICAgICAgZlBhdHRlcm47CiAgICAvLyBsYXRlciwgYWxsb3cgbW9yZSB0aGFuIHRlbiBpdGVtcwogICAgRm9ybWF0ICAgICAgICAgICAgICAgICAqZkZvcm1hdHNba01heEZvcm1hdF07CiAgICBpbnQzMl90ICAgICAgICAgICAgICpmT2Zmc2V0czsKICAgIGludDMyX3QgICAgICAgICAgICAgZkNvdW50OwogICAgaW50MzJfdCAgICAgICAgICAgICAqZkFyZ3VtZW50TnVtYmVyczsKICAgIGludDMyX3QgICAgICAgICAgICAgZk1heE9mZnNldDsKICAgIAogICAgLyoqCiAgICAgKiBJbnRlcm5hbCByb3V0aW5lIHVzZWQgYnkgZm9ybWF0LgogICAgICogQHBhcmFtIHJlY3Vyc2lvblByb3RlY3Rpb24gSW5pdGlhbGx5IHplcm8uIEJpdHMgMC4uOSBhcmUgdXNlZCB0byBpbmRpY2F0ZQogICAgICogdGhhdCBhIHBhcmFtZXRlciBoYXMgYWxyZWFkeSBiZWVuIHNlZW4sIHRvIGF2b2lkIHJlY3Vyc2lvbi4gIEN1cnJlbnRseQogICAgICogdW51c2VkLgogICAgICovCiAgICBzdGF0aWMgY29uc3QgaW50MzJfdCAgICAgICAgIGZnTGlzdExlbmd0aDsKICAgIHN0YXRpYyBjb25zdCBVbmljb2RlU3RyaW5nICAgICBmZ1R5cGVMaXN0W107CiAgICBzdGF0aWMgY29uc3QgVW5pY29kZVN0cmluZyAgICAgZmdNb2RpZmllckxpc3RbXTsKICAgIHN0YXRpYyBjb25zdCBVbmljb2RlU3RyaW5nICAgICBmZ0RhdGVNb2RpZmllckxpc3RbXTsKCiAgICAvKiogCiAgICAgKiBGaW5kcyB0aGUgd29yZCBzLCBpbiB0aGUga2V5d29yZCBsaXN0IGFuZCByZXR1cm5zIHRoZSBsb2NhdGVkIGluZGV4LgogICAgICogQHBhcmFtIHMgdGhlIGtleXdvcmQgdG8gYmUgc2VhcmNoZWQgZm9yLgogICAgICogQHBhcmFtIGxpc3QgdGhlIGxpc3Qgb2Yga2V5d29yZHMgdG8gYmUgc2VhcmNoZWQgd2l0aC4KICAgICAqIEByZXR1cm4gdGhlIGluZGV4IG9mIHRoZSBsaXN0IHdoaWNoIG1hdGNoZXMgdGhlIGtleXdvcmQgcy4KICAgICAqLwogICAgc3RhdGljIGludDMyX3QgZmluZEtleXdvcmQoIGNvbnN0IFVuaWNvZGVTdHJpbmcmIHMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgVW5pY29kZVN0cmluZyogbGlzdCk7CgogICAgLyoqCiAgICAgKiBGb3JtYXRzIHRoZSBhcnJheSBvZiBhcmd1bWVudHMgYW5kIGNvcGllcyB0aGUgcmVzdWx0IGludG8gdGhlIHJlc3VsdCBidWZmZXIsCiAgICAgKiB1cGRhdGVzIHRoZSBmaWVsZCBwb3NpdGlvbi4KICAgICAqIEBwYXJhbSBhcmd1bWVudHMgdGhlIGZvcm1hdHRhYmxlIG9iamVjdHMgYXJyYXkuCiAgICAgKiBAcGFyYW0gY250IHRoZSBhcnJheSBjb3VudC4KICAgICAqIEBwYXJhbSBzdGF0dXMgZmllbGQgcG9zaXRpb24gc3RhdHVzLgogICAgICogQHBhcmFtIHJlY3Vyc2lvblByb3RlY3Rpb24gSW5pdGlhbGx5IHplcm8uIEJpdHMgMC4uOSBhcmUgdXNlZCB0byBpbmRpY2F0ZQogICAgICogdGhhdCBhIHBhcmFtZXRlciBoYXMgYWxyZWFkeSBiZWVuIHNlZW4sIHRvIGF2b2lkIHJlY3Vyc2lvbi4gIEN1cnJlbnRseQogICAgICogdW51c2VkLgogICAgICogQHBhcmFtIHN1Y2Nlc3MgdGhlIGVycm9yIGNvZGUgc3RhdHVzLgogICAgICovCiAgICBVbmljb2RlU3RyaW5nJiAgZm9ybWF0KCBjb25zdCBGb3JtYXR0YWJsZSogYXJndW1lbnRzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludDMyX3QgY250LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVuaWNvZGVTdHJpbmcmIHJlc3VsdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBGaWVsZFBvc2l0aW9uJiBzdGF0dXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50MzJfdCByZWN1cnNpb25Qcm90ZWN0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3VjY2VzcykgY29uc3Q7CgogICAgLyoqCiAgICAgKiBDaGVja3MgdGhlIHNlZ21lbnRzIGZvciB0aGUgY2xvc2VzdCBtYXRjaGVkIGZvcm1hdCBpbnN0YW5jZSBhbmQKICAgICAqIHVwZGF0ZXMgdGhlIGZvcm1hdCBhcnJheSB3aXRoIHRoZSBuZXcgZm9ybWF0IGluc3RhbmNlLgogICAgICogQHBhcmFtIHBvc2l0aW9uIHRoZSBsYXN0IHByb2Nlc3NlZCBvZmZzZXQgaW4gdGhlIHBhdHRlcm4gCiAgICAgKiBAcGFyYW0gb2Zmc2V0TnVtYmVyIHRoZSBvZmZzZXQgbnVtYmVyIG9mIHRoZSBsYXN0IHByb2Nlc3NlZCBzZWdtZW50CiAgICAgKiBAcGFyYW0gc2VnbWVudHMgdGhlIHN0cmluZyB0aGF0IGNvbnRhaW5zIHRoZSBwYXJzZWQgcGF0dGVybiBzZWdtZW50cy4KICAgICAqIEBwYXJhbSBzdWNjZXNzIHRoZSBlcnJvciBjb2RlCiAgICAgKi8KICAgIHZvaWQgICAgICAgICAgICBtYWtlRm9ybWF0KCBpbnQzMl90IHBvc2l0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90IG9mZnNldE51bWJlciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVW5pY29kZVN0cmluZyogc2VnbWVudHMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN1Y2Nlc3MpOwoKICAgIC8qKgogICAgICogQ29udmVuaWVuY2UgbWV0aG9kIHRoYXQgb3VnaHQgdG8gYmUgaW4gTnVtYmVyRm9ybWF0CiAgICAgKi8KICAgIE51bWJlckZvcm1hdCogY3JlYXRlSW50ZWdlckZvcm1hdChjb25zdCBMb2NhbGUmIGxvY2FsZSwgVUVycm9yQ29kZSYgc3RhdHVzKSBjb25zdDsKCiAgICAvKioKICAgICAqIENoZWNrcyB0aGUgcmFuZ2Ugb2YgdGhlIHNvdXJjZSB0ZXh0IHRvIHF1b3RlIHRoZSBzcGVjaWFsCiAgICAgKiBjaGFyYWN0ZXJzLCB7IGFuZCAnIGFuZCBjb3B5IHRvIHRhcmdldCBidWZmZXIuCiAgICAgKiBAcGFyYW0gc291cmNlCiAgICAgKiBAcGFyYW0gc3RhcnQgdGhlIHRleHQgb2Zmc2V0IHRvIHN0YXJ0IHRoZSBwcm9jZXNzIG9mIGluIHRoZSBzb3VyY2Ugc3RyaW5nCiAgICAgKiBAcGFyYW0gZW5kIHRoZSB0ZXh0IG9mZnNldCB0byBlbmQgdGhlIHByb2Nlc3Mgb2YgaW4gdGhlIHNvdXJjZSBzdHJpbmcKICAgICAqIEBwYXJhbSB0YXJnZXQgdGhlIHJlc3VsdCBidWZmZXIKICAgICAqLwogICAgc3RhdGljIHZvaWQgY29weUFuZEZpeFF1b3Rlcyhjb25zdCBVbmljb2RlU3RyaW5nJiBzb3VyY2UsIGludDMyX3Qgc3RhcnQsIGludDMyX3QgZW5kLCBVbmljb2RlU3RyaW5nJiB0YXJnZXQpOwoKICAgIC8qKgogICAgICogQ29udmVydHMgYSBzdHJpbmcgdG8gYW4gaW50ZWdlciB2YWx1ZSB1c2luZyBhIGRlZmF1bHQgTnVtYmVyRm9ybWF0IG9iamVjdAogICAgICogd2hpY2ggaXMgc3RhdGljIChzaGFyZWQgYnkgYWxsIE1lc3NhZ2VGb3JtYXQgaW5zdGFuY2VzKS4gIFRoaXMgcmVwbGFjZXMKICAgICAqIGEgY2FsbCB0byB3dG9pKCkuCiAgICAgKiBAcGFyYW0gc3RyaW5nIHRoZSBzb3VyY2Ugc3RyaW5nIHRvIGNvbnZlcnQgd2l0aAogICAgICogQHBhcmFtIHN0YXR1cyB0aGUgZXJyb3IgY29kZS4KICAgICAqIEByZXR1cm4gdGhlIGNvbnZlcnRlZCBudW1iZXIuCiAgICAgKi8KICAgIHN0YXRpYyBpbnQzMl90IHN0b2koY29uc3QgVW5pY29kZVN0cmluZyYgc3RyaW5nLCBVRXJyb3JDb2RlJiBzdGF0dXMpOwoKICAgIC8qKgogICAgICogQ29udmVydHMgYW4gaW50ZWdlciB2YWx1ZSB0byBhIHN0cmluZyB1c2luZyBhIGRlZmF1bHQgTnVtYmVyRm9ybWF0IG9iamVjdAogICAgICogd2hpY2ggaXMgc3RhdGljIChzaGFyZWQgYnkgYWxsIE1lc3NhZ2VGb3JtYXQgaW5zdGFuY2VzKS4gIFRoaXMgcmVwbGFjZXMKICAgICAqIGEgY2FsbCB0byB3dG9pKCkuCiAgICAgKiBAcGFyYW0gaSB0aGUgaW50ZWdlciB0byBmb3JtYXQKICAgICAqIEBwYXJhbSBzdHJpbmcgdGhlIGRlc3RpbmF0aW9uIHN0cmluZwogICAgICogQHJldHVybiBhIHJlZmVyZW5jZSB0byBzdHJpbmcuCiAgICAgKi8KICAgIHN0YXRpYyBVbmljb2RlU3RyaW5nJiBpdG9zKGludDMyX3QgaSwgVW5pY29kZVN0cmluZyYgc3RyaW5nKTsKfTsKIAppbmxpbmUgVUNsYXNzSUQgCk1lc3NhZ2VGb3JtYXQ6OmdldER5bmFtaWNDbGFzc0lEKCkgY29uc3QKeyAKICAgIHJldHVybiBNZXNzYWdlRm9ybWF0OjpnZXRTdGF0aWNDbGFzc0lEKCk7IAp9CgppbmxpbmUgVW5pY29kZVN0cmluZyYKTWVzc2FnZUZvcm1hdDo6Zm9ybWF0KGNvbnN0IEZvcm1hdHRhYmxlJiBvYmosCiAgICAgICAgICAgICAgICAgICAgICBVbmljb2RlU3RyaW5nJiByZXN1bHQsCiAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIGNvbnN0IHsKICAgIHJldHVybiBGb3JtYXQ6OmZvcm1hdChvYmosIHJlc3VsdCwgc3RhdHVzKTsKfQoKI2VuZGlmIC8vIF9NU0dGTVQKLy9lb2YK