LyoKICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZSBvciBtb3JlCiAqIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCiAqIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlIHRvIFlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wCiAqICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqIAogKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKiAKICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQogKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAogKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KICovCnBhY2thZ2Ugb3JnLmFwYWNoZS5jb21tb25zLnRleHQuYmV0YTsKCmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMubGFuZzMuU3RyaW5nVXRpbHM7CmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMudGV4dC5iZXRhLnRyYW5zbGF0ZS5BZ2dyZWdhdGVUcmFuc2xhdG9yOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLnRleHQuYmV0YS50cmFuc2xhdGUuQ2hhclNlcXVlbmNlVHJhbnNsYXRvcjsKaW1wb3J0IG9yZy5hcGFjaGUuY29tbW9ucy50ZXh0LmJldGEudHJhbnNsYXRlLkNzdlRyYW5zbGF0b3JzOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLnRleHQuYmV0YS50cmFuc2xhdGUuRW50aXR5QXJyYXlzOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLnRleHQuYmV0YS50cmFuc2xhdGUuSmF2YVVuaWNvZGVFc2NhcGVyOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLnRleHQuYmV0YS50cmFuc2xhdGUuTG9va3VwVHJhbnNsYXRvcjsKaW1wb3J0IG9yZy5hcGFjaGUuY29tbW9ucy50ZXh0LmJldGEudHJhbnNsYXRlLk51bWVyaWNFbnRpdHlFc2NhcGVyOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLnRleHQuYmV0YS50cmFuc2xhdGUuTnVtZXJpY0VudGl0eVVuZXNjYXBlcjsKaW1wb3J0IG9yZy5hcGFjaGUuY29tbW9ucy50ZXh0LmJldGEudHJhbnNsYXRlLk9jdGFsVW5lc2NhcGVyOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLnRleHQuYmV0YS50cmFuc2xhdGUuU2luZ2xlTG9va3VwVHJhbnNsYXRvcjsKaW1wb3J0IG9yZy5hcGFjaGUuY29tbW9ucy50ZXh0LmJldGEudHJhbnNsYXRlLlVuaWNvZGVVbmVzY2FwZXI7CmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMudGV4dC5iZXRhLnRyYW5zbGF0ZS5Vbmljb2RlVW5wYWlyZWRTdXJyb2dhdGVSZW1vdmVyOwoKaW1wb3J0IGphdmEuaW8uSU9FeGNlcHRpb247CmltcG9ydCBqYXZhLmlvLldyaXRlcjsKaW1wb3J0IGphdmEudXRpbC5Db2xsZWN0aW9uczsKaW1wb3J0IGphdmEudXRpbC5IYXNoTWFwOwppbXBvcnQgamF2YS51dGlsLk1hcDsKCi8qKgogKiA8cD5Fc2NhcGVzIGFuZCB1bmVzY2FwZXMge0Bjb2RlIFN0cmluZ31zIGZvcgogKiBKYXZhLCBKYXZhIFNjcmlwdCwgSFRNTCBhbmQgWE1MLjwvcD4KICoKICogPHA+I1RocmVhZFNhZmUjPC9wPgogKgogKgogKiA8cD4KICogVGhpcyBjb2RlIGhhcyBiZWVuIGFkYXB0ZWQgZnJvbSBBcGFjaGUgQ29tbW9ucyBMYW5nIDMuNS4KICogPC9wPgogKgogKiBAc2luY2UgMS4wCiAqLwpwdWJsaWMgY2xhc3MgU3RyaW5nRXNjYXBlVXRpbHMgewoKICAgIC8qIEVTQ0FQRSBUUkFOU0xBVE9SUyAqLwoKICAgIC8qKgogICAgICogVHJhbnNsYXRvciBvYmplY3QgZm9yIGVzY2FwaW5nIEphdmEuIAogICAgICoKICAgICAqIFdoaWxlIHtAbGluayAjZXNjYXBlSmF2YShTdHJpbmcpfSBpcyB0aGUgZXhwZWN0ZWQgbWV0aG9kIG9mIHVzZSwgdGhpcyAKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIEphdmEgZXNjYXBpbmcgZnVuY3Rpb25hbGl0eSB0byBiZSB1c2VkIAogICAgICogYXMgdGhlIGZvdW5kYXRpb24gZm9yIGEgY3VzdG9tIHRyYW5zbGF0b3IuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciBFU0NBUEVfSkFWQTsKICAgIHN0YXRpYyB7CiAgICAgICAgTWFwPENoYXJTZXF1ZW5jZSwgQ2hhclNlcXVlbmNlPiBlc2NhcGVKYXZhTWFwID0gbmV3IEhhc2hNYXA8PigpOwogICAgICAgIGVzY2FwZUphdmFNYXAucHV0KCJcIiIsICJcXFwiIik7CiAgICAgICAgZXNjYXBlSmF2YU1hcC5wdXQoIlxcIiwgIlxcXFwiKTsKICAgICAgICBFU0NBUEVfSkFWQSA9IG5ldyBBZ2dyZWdhdGVUcmFuc2xhdG9yKAogICAgICAgICAgICAgICAgbmV3IExvb2t1cFRyYW5zbGF0b3IoQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTWFwKGVzY2FwZUphdmFNYXApKSwKICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKEVudGl0eUFycmF5cy5KQVZBX0NUUkxfQ0hBUlNfRVNDQVBFKSwKICAgICAgICAgICAgICAgIEphdmFVbmljb2RlRXNjYXBlci5vdXRzaWRlT2YoMzIsIDB4N2YpCiAgICAgICAgKTsKICAgIH0KCiAgICAvKioKICAgICAqIFRyYW5zbGF0b3Igb2JqZWN0IGZvciBlc2NhcGluZyBFY21hU2NyaXB0L0phdmFTY3JpcHQuIAogICAgICoKICAgICAqIFdoaWxlIHtAbGluayAjZXNjYXBlRWNtYVNjcmlwdChTdHJpbmcpfSBpcyB0aGUgZXhwZWN0ZWQgbWV0aG9kIG9mIHVzZSwgdGhpcyAKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIEVjbWFTY3JpcHQgZXNjYXBpbmcgZnVuY3Rpb25hbGl0eSB0byBiZSB1c2VkIAogICAgICogYXMgdGhlIGZvdW5kYXRpb24gZm9yIGEgY3VzdG9tIHRyYW5zbGF0b3IuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciBFU0NBUEVfRUNNQVNDUklQVDsKICAgIHN0YXRpYyB7CiAgICAgICAgTWFwPENoYXJTZXF1ZW5jZSwgQ2hhclNlcXVlbmNlPiBlc2NhcGVFY21hU2NyaXB0TWFwID0gbmV3IEhhc2hNYXA8PigpOwogICAgICAgIGVzY2FwZUVjbWFTY3JpcHRNYXAucHV0KCInIiwgIlxcJyIpOwogICAgICAgIGVzY2FwZUVjbWFTY3JpcHRNYXAucHV0KCJcIiIsICJcXFwiIik7CiAgICAgICAgZXNjYXBlRWNtYVNjcmlwdE1hcC5wdXQoIlxcIiwgIlxcXFwiKTsKICAgICAgICBlc2NhcGVFY21hU2NyaXB0TWFwLnB1dCgiLyIsICJcXC8iKTsKICAgICAgICBFU0NBUEVfRUNNQVNDUklQVCA9IG5ldyBBZ2dyZWdhdGVUcmFuc2xhdG9yKAogICAgICAgICAgICAgICAgbmV3IExvb2t1cFRyYW5zbGF0b3IoQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTWFwKGVzY2FwZUVjbWFTY3JpcHRNYXApKSwKICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKEVudGl0eUFycmF5cy5KQVZBX0NUUkxfQ0hBUlNfRVNDQVBFKSwKICAgICAgICAgICAgICAgIEphdmFVbmljb2RlRXNjYXBlci5vdXRzaWRlT2YoMzIsIDB4N2YpCiAgICAgICAgKTsKICAgIH0KCiAgICAvKioKICAgICAqIFRyYW5zbGF0b3Igb2JqZWN0IGZvciBlc2NhcGluZyBKc29uLgogICAgICoKICAgICAqIFdoaWxlIHtAbGluayAjZXNjYXBlSnNvbihTdHJpbmcpfSBpcyB0aGUgZXhwZWN0ZWQgbWV0aG9kIG9mIHVzZSwgdGhpcwogICAgICogb2JqZWN0IGFsbG93cyB0aGUgSnNvbiBlc2NhcGluZyBmdW5jdGlvbmFsaXR5IHRvIGJlIHVzZWQKICAgICAqIGFzIHRoZSBmb3VuZGF0aW9uIGZvciBhIGN1c3RvbSB0cmFuc2xhdG9yLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgRVNDQVBFX0pTT047CiAgICBzdGF0aWMgewogICAgICAgIE1hcDxDaGFyU2VxdWVuY2UsIENoYXJTZXF1ZW5jZT4gZXNjYXBlSnNvbk1hcCA9IG5ldyBIYXNoTWFwPD4oKTsKICAgICAgICBlc2NhcGVKc29uTWFwLnB1dCgiXCIiLCAiXFxcIiIpOwogICAgICAgIGVzY2FwZUpzb25NYXAucHV0KCJcXCIsICJcXFxcIik7CiAgICAgICAgZXNjYXBlSnNvbk1hcC5wdXQoIi8iLCAiXFwvIik7CiAgICAgICAgRVNDQVBFX0pTT04gPSBuZXcgQWdncmVnYXRlVHJhbnNsYXRvcigKICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKENvbGxlY3Rpb25zLnVubW9kaWZpYWJsZU1hcChlc2NhcGVKc29uTWFwKSksCiAgICAgICAgICAgICAgICBuZXcgTG9va3VwVHJhbnNsYXRvcihFbnRpdHlBcnJheXMuSkFWQV9DVFJMX0NIQVJTX0VTQ0FQRSksCiAgICAgICAgICAgICAgICBKYXZhVW5pY29kZUVzY2FwZXIub3V0c2lkZU9mKDMyLCAweDdmKQogICAgICAgICk7CiAgICB9CgogICAgLyoqCiAgICAgKiBUcmFuc2xhdG9yIG9iamVjdCBmb3IgZXNjYXBpbmcgWE1MIDEuMC4KICAgICAqCiAgICAgKiBXaGlsZSB7QGxpbmsgI2VzY2FwZVhtbDEwKFN0cmluZyl9IGlzIHRoZSBleHBlY3RlZCBtZXRob2Qgb2YgdXNlLCB0aGlzCiAgICAgKiBvYmplY3QgYWxsb3dzIHRoZSBYTUwgZXNjYXBpbmcgZnVuY3Rpb25hbGl0eSB0byBiZSB1c2VkCiAgICAgKiBhcyB0aGUgZm91bmRhdGlvbiBmb3IgYSBjdXN0b20gdHJhbnNsYXRvci4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBDaGFyU2VxdWVuY2VUcmFuc2xhdG9yIEVTQ0FQRV9YTUwxMDsKICAgIHN0YXRpYyB7CiAgICAgICAgTWFwPENoYXJTZXF1ZW5jZSwgQ2hhclNlcXVlbmNlPiBlc2NhcGVYbWwxME1hcCA9IG5ldyBIYXNoTWFwPD4oKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwMCIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwMSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwMiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwMyIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwNCIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwNSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwNiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwNyIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwOCIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwYiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwYyIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwZSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAwZiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxMCIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxMSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxMiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxMyIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxNCIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxNSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxNiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxNyIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxOCIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxOSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxYSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxYiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxYyIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxZCIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxZSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1MDAxZiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1ZmZmZSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxME1hcC5wdXQoIlx1ZmZmZiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBFU0NBUEVfWE1MMTAgPSBuZXcgQWdncmVnYXRlVHJhbnNsYXRvcigKICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKEVudGl0eUFycmF5cy5CQVNJQ19FU0NBUEUpLAogICAgICAgICAgICAgICAgbmV3IExvb2t1cFRyYW5zbGF0b3IoRW50aXR5QXJyYXlzLkFQT1NfRVNDQVBFKSwKICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKENvbGxlY3Rpb25zLnVubW9kaWZpYWJsZU1hcChlc2NhcGVYbWwxME1hcCkpLAogICAgICAgICAgICAgICAgTnVtZXJpY0VudGl0eUVzY2FwZXIuYmV0d2VlbigweDdmLCAweDg0KSwKICAgICAgICAgICAgICAgIE51bWVyaWNFbnRpdHlFc2NhcGVyLmJldHdlZW4oMHg4NiwgMHg5ZiksCiAgICAgICAgICAgICAgICBuZXcgVW5pY29kZVVucGFpcmVkU3Vycm9nYXRlUmVtb3ZlcigpCiAgICAgICAgKTsKICAgIH0KCiAgICAvKioKICAgICAqIFRyYW5zbGF0b3Igb2JqZWN0IGZvciBlc2NhcGluZyBYTUwgMS4xLgogICAgICoKICAgICAqIFdoaWxlIHtAbGluayAjZXNjYXBlWG1sMTEoU3RyaW5nKX0gaXMgdGhlIGV4cGVjdGVkIG1ldGhvZCBvZiB1c2UsIHRoaXMKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIFhNTCBlc2NhcGluZyBmdW5jdGlvbmFsaXR5IHRvIGJlIHVzZWQKICAgICAqIGFzIHRoZSBmb3VuZGF0aW9uIGZvciBhIGN1c3RvbSB0cmFuc2xhdG9yLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgRVNDQVBFX1hNTDExOwogICAgc3RhdGljIHsKICAgICAgICBNYXA8Q2hhclNlcXVlbmNlLCBDaGFyU2VxdWVuY2U+IGVzY2FwZVhtbDExTWFwID0gbmV3IEhhc2hNYXA8PigpOwogICAgICAgIGVzY2FwZVhtbDExTWFwLnB1dCgiXHUwMDAwIiwgU3RyaW5nVXRpbHMuRU1QVFkpOwogICAgICAgIGVzY2FwZVhtbDExTWFwLnB1dCgiXHUwMDBiIiwgIiYjMTE7Iik7CiAgICAgICAgZXNjYXBlWG1sMTFNYXAucHV0KCJcdTAwMGMiLCAiJiMxMjsiKTsKICAgICAgICBlc2NhcGVYbWwxMU1hcC5wdXQoIlx1ZmZmZSIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBlc2NhcGVYbWwxMU1hcC5wdXQoIlx1ZmZmZiIsIFN0cmluZ1V0aWxzLkVNUFRZKTsKICAgICAgICBFU0NBUEVfWE1MMTEgPSBuZXcgQWdncmVnYXRlVHJhbnNsYXRvcigKICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKEVudGl0eUFycmF5cy5CQVNJQ19FU0NBUEUpLAogICAgICAgICAgICAgICAgbmV3IExvb2t1cFRyYW5zbGF0b3IoRW50aXR5QXJyYXlzLkFQT1NfRVNDQVBFKSwKICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKENvbGxlY3Rpb25zLnVubW9kaWZpYWJsZU1hcChlc2NhcGVYbWwxMU1hcCkpLAogICAgICAgICAgICAgICAgTnVtZXJpY0VudGl0eUVzY2FwZXIuYmV0d2VlbigweDEsIDB4OCksCiAgICAgICAgICAgICAgICBOdW1lcmljRW50aXR5RXNjYXBlci5iZXR3ZWVuKDB4ZSwgMHgxZiksCiAgICAgICAgICAgICAgICBOdW1lcmljRW50aXR5RXNjYXBlci5iZXR3ZWVuKDB4N2YsIDB4ODQpLAogICAgICAgICAgICAgICAgTnVtZXJpY0VudGl0eUVzY2FwZXIuYmV0d2VlbigweDg2LCAweDlmKSwKICAgICAgICAgICAgICAgIG5ldyBVbmljb2RlVW5wYWlyZWRTdXJyb2dhdGVSZW1vdmVyKCkKICAgICAgICApOwogICAgfQoKICAgIC8qKgogICAgICogVHJhbnNsYXRvciBvYmplY3QgZm9yIGVzY2FwaW5nIEhUTUwgdmVyc2lvbiAzLjAuCiAgICAgKgogICAgICogV2hpbGUge0BsaW5rICNlc2NhcGVIdG1sMyhTdHJpbmcpfSBpcyB0aGUgZXhwZWN0ZWQgbWV0aG9kIG9mIHVzZSwgdGhpcyAKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIEhUTUwgZXNjYXBpbmcgZnVuY3Rpb25hbGl0eSB0byBiZSB1c2VkIAogICAgICogYXMgdGhlIGZvdW5kYXRpb24gZm9yIGEgY3VzdG9tIHRyYW5zbGF0b3IuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciBFU0NBUEVfSFRNTDMgPQogICAgICAgICAgICBuZXcgQWdncmVnYXRlVHJhbnNsYXRvcigKICAgICAgICAgICAgICAgICAgICBuZXcgTG9va3VwVHJhbnNsYXRvcihFbnRpdHlBcnJheXMuQkFTSUNfRVNDQVBFKSwKICAgICAgICAgICAgICAgICAgICBuZXcgTG9va3VwVHJhbnNsYXRvcihFbnRpdHlBcnJheXMuSVNPODg1OV8xX0VTQ0FQRSkKICAgICAgICAgICAgKTsKCiAgICAvKioKICAgICAqIFRoZSBpbXByb3ZlZCB0cmFuc2xhdG9yIG9iamVjdCBmb3IgZXNjYXBpbmcgSFRNTCB2ZXJzaW9uIDMuMC4KICAgICAqIFRoZSAnaW1wcm92ZWQnIHBhcnQgb2YgdGhpcyB0cmFuc2xhdG9yIGlzIHRoYXQgaXQgY2hlY2tzIGlmIHRoZSBodG1sIGlzIGFscmVhZHkgdHJhbnNsYXRlZC4KICAgICAqIFRoaXMgY2hlY2sgcHJldmVudHMgZG91YmxlLCB0cmlwbGUsIG9yIHJlY3Vyc2l2ZSB0cmFuc2xhdGlvbnMuCiAgICAgKgogICAgICogV2hpbGUge0BsaW5rICNlc2NhcGVIdG1sM09uY2UoU3RyaW5nKX0gaXMgdGhlIGV4cGVjdGVkIG1ldGhvZCBvZiB1c2UsIHRoaXMKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIEhUTUwgZXNjYXBpbmcgZnVuY3Rpb25hbGl0eSB0byBiZSB1c2VkCiAgICAgKiBhcyB0aGUgZm91bmRhdGlvbiBmb3IgYSBjdXN0b20gdHJhbnNsYXRvci4KICAgICAqCiAgICAgKiBOb3RlIHRoYXQsIG11bHRpcGxlIGxvb2t1cCB0YWJsZXMgc2hvdWxkIGJlIHBhc3NlZCB0byB0aGlzIHRyYW5zbGF0b3IKICAgICAqIGluc3RlYWQgb2YgcGFzc2luZyBtdWx0aXBsZSBpbnN0YW5jZXMgb2YgdGhpcyB0cmFuc2xhdG9yIHRvIHRoZQogICAgICogQWdncmVnYXRlVHJhbnNsYXRvci4gQmVjYXVzZSwgYSBTaW5nbGVMb29rdXBUcmFuc2xhdG9yIG9ubHkgY2hlY2tzIHRoZSB2YWx1ZXMgb2YgdGhlCiAgICAgKiBsb29rdXAgdGFibGUgcGFzc2VkIHRvIHRoYXQgaW5zdGFuY2Ugd2hpbGUgZGVjaWRpbmcgd2hldGhlciBhIHZhbHVlIGlzCiAgICAgKiBhbHJlYWR5IHRyYW5zbGF0ZWQgb3Igbm90LgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgRVNDQVBFX0hUTUwzX09OQ0UgPQogICAgICAgICAgICBuZXcgU2luZ2xlTG9va3VwVHJhbnNsYXRvcihFbnRpdHlBcnJheXMuQkFTSUNfRVNDQVBFLCBFbnRpdHlBcnJheXMuSVNPODg1OV8xX0VTQ0FQRSk7CgoKICAgIC8qKgogICAgICogVHJhbnNsYXRvciBvYmplY3QgZm9yIGVzY2FwaW5nIEhUTUwgdmVyc2lvbiA0LjAuCiAgICAgKgogICAgICogV2hpbGUge0BsaW5rICNlc2NhcGVIdG1sNChTdHJpbmcpfSBpcyB0aGUgZXhwZWN0ZWQgbWV0aG9kIG9mIHVzZSwgdGhpcyAKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIEhUTUwgZXNjYXBpbmcgZnVuY3Rpb25hbGl0eSB0byBiZSB1c2VkIAogICAgICogYXMgdGhlIGZvdW5kYXRpb24gZm9yIGEgY3VzdG9tIHRyYW5zbGF0b3IuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciBFU0NBUEVfSFRNTDQgPQogICAgICAgICAgICBuZXcgQWdncmVnYXRlVHJhbnNsYXRvcigKICAgICAgICAgICAgICAgICAgICBuZXcgTG9va3VwVHJhbnNsYXRvcihFbnRpdHlBcnJheXMuQkFTSUNfRVNDQVBFKSwKICAgICAgICAgICAgICAgICAgICBuZXcgTG9va3VwVHJhbnNsYXRvcihFbnRpdHlBcnJheXMuSVNPODg1OV8xX0VTQ0FQRSksCiAgICAgICAgICAgICAgICAgICAgbmV3IExvb2t1cFRyYW5zbGF0b3IoRW50aXR5QXJyYXlzLkhUTUw0MF9FWFRFTkRFRF9FU0NBUEUpCiAgICAgICAgICAgICk7CgogICAgLyoqCiAgICAgKiBUaGUgaW1wcm92ZWQgdHJhbnNsYXRvciBvYmplY3QgZm9yIGVzY2FwaW5nIEhUTUwgdmVyc2lvbiA0LjAuCiAgICAgKiBUaGUgJ2ltcHJvdmVkJyBwYXJ0IG9mIHRoaXMgdHJhbnNsYXRvciBpcyB0aGF0IGl0IGNoZWNrcyBpZiB0aGUgaHRtbCBpcyBhbHJlYWR5IHRyYW5zbGF0ZWQuCiAgICAgKiBUaGlzIGNoZWNrIHByZXZlbnRzIGRvdWJsZSwgdHJpcGxlLCBvciByZWN1cnNpdmUgdHJhbnNsYXRpb25zLgogICAgICoKICAgICAqIFdoaWxlIHtAbGluayAjZXNjYXBlSHRtbDRPbmNlKFN0cmluZyl9IGlzIHRoZSBleHBlY3RlZCBtZXRob2Qgb2YgdXNlLCB0aGlzCiAgICAgKiBvYmplY3QgYWxsb3dzIHRoZSBIVE1MIGVzY2FwaW5nIGZ1bmN0aW9uYWxpdHkgdG8gYmUgdXNlZAogICAgICogYXMgdGhlIGZvdW5kYXRpb24gZm9yIGEgY3VzdG9tIHRyYW5zbGF0b3IuCiAgICAgKgogICAgICogTm90ZSB0aGF0LCBtdWx0aXBsZSBsb29rdXAgdGFibGVzIHNob3VsZCBiZSBwYXNzZWQgdG8gdGhpcyB0cmFuc2xhdG9yCiAgICAgKiBpbnN0ZWFkIG9mIHBhc3NpbmcgbXVsdGlwbGUgaW5zdGFuY2VzIG9mIHRoaXMgdHJhbnNsYXRvciB0byB0aGUKICAgICAqIEFnZ3JlZ2F0ZVRyYW5zbGF0b3IuIEJlY2F1c2UsIGEgU2luZ2xlTG9va3VwVHJhbnNsYXRvciBvbmx5IGNoZWNrcyB0aGUgdmFsdWVzIG9mIHRoZQogICAgICogbG9va3VwIHRhYmxlIHBhc3NlZCB0byB0aGF0IGluc3RhbmNlIHdoaWxlIGRlY2lkaW5nIHdoZXRoZXIgYSB2YWx1ZSBpcwogICAgICogYWxyZWFkeSB0cmFuc2xhdGVkIG9yIG5vdC4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBDaGFyU2VxdWVuY2VUcmFuc2xhdG9yIEVTQ0FQRV9IVE1MNF9PTkNFID0KICAgICAgICAgICAgbmV3IFNpbmdsZUxvb2t1cFRyYW5zbGF0b3IoCiAgICAgICAgICAgICAgICAgICAgRW50aXR5QXJyYXlzLkJBU0lDX0VTQ0FQRSwKICAgICAgICAgICAgICAgICAgICBFbnRpdHlBcnJheXMuSVNPODg1OV8xX0VTQ0FQRSwKICAgICAgICAgICAgICAgICAgICBFbnRpdHlBcnJheXMuSFRNTDQwX0VYVEVOREVEX0VTQ0FQRQogICAgICAgICAgICApOwoKICAgIC8qKgogICAgICogVHJhbnNsYXRvciBvYmplY3QgZm9yIGVzY2FwaW5nIGluZGl2aWR1YWwgQ29tbWEgU2VwYXJhdGVkIFZhbHVlcy4gCiAgICAgKgogICAgICogV2hpbGUge0BsaW5rICNlc2NhcGVDc3YoU3RyaW5nKX0gaXMgdGhlIGV4cGVjdGVkIG1ldGhvZCBvZiB1c2UsIHRoaXMgCiAgICAgKiBvYmplY3QgYWxsb3dzIHRoZSBDU1YgZXNjYXBpbmcgZnVuY3Rpb25hbGl0eSB0byBiZSB1c2VkIAogICAgICogYXMgdGhlIGZvdW5kYXRpb24gZm9yIGEgY3VzdG9tIHRyYW5zbGF0b3IuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciBFU0NBUEVfQ1NWID0gbmV3IENzdlRyYW5zbGF0b3JzLkNzdkVzY2FwZXIoKTsKCiAgICAvKioKICAgICAqIFRyYW5zbGF0b3Igb2JqZWN0IGZvciBlc2NhcGluZyBTaGVsbCBjb21tYW5kIGxhbmd1YWdlLgogICAgICoKICAgICAqIEBzZWUgPGEgaHJlZj0iaHR0cDovL3B1YnMub3Blbmdyb3VwLm9yZy9vbmxpbmVwdWJzLzc5MDg3OTkveGN1L2NoYXAyLmh0bWwiPlNoZWxsIENvbW1hbmQgTGFuZ3VhZ2U8L2E+CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciBFU0NBUEVfWFNJOwogICAgc3RhdGljIHsKICAgICAgICBNYXA8Q2hhclNlcXVlbmNlLCBDaGFyU2VxdWVuY2U+IGVzY2FwZVhzaU1hcCA9IG5ldyBIYXNoTWFwPD4oKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCJ8IiwgIlxcfCIpOwogICAgICAgIGVzY2FwZVhzaU1hcC5wdXQoIiYiLCAiXFwmIik7CiAgICAgICAgZXNjYXBlWHNpTWFwLnB1dCgiOyIsICJcXDsiKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCI8IiwgIlxcPCIpOwogICAgICAgIGVzY2FwZVhzaU1hcC5wdXQoIj4iLCAiXFw+Iik7CiAgICAgICAgZXNjYXBlWHNpTWFwLnB1dCgiKCIsICJcXCgiKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCIpIiwgIlxcKSIpOwogICAgICAgIGVzY2FwZVhzaU1hcC5wdXQoIiQiLCAiXFwkIik7CiAgICAgICAgZXNjYXBlWHNpTWFwLnB1dCgiYCIsICJcXGAiKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCJcXCIsICJcXFxcIik7CiAgICAgICAgZXNjYXBlWHNpTWFwLnB1dCgiXCIiLCAiXFxcIiIpOwogICAgICAgIGVzY2FwZVhzaU1hcC5wdXQoIiciLCAiXFwnIik7CiAgICAgICAgZXNjYXBlWHNpTWFwLnB1dCgiICIsICJcXCAiKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCJcdCIsICJcXFx0Iik7CiAgICAgICAgZXNjYXBlWHNpTWFwLnB1dCgiXHJcbiIsICIiKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCJcbiIsICIiKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCIqIiwgIlxcKiIpOwogICAgICAgIGVzY2FwZVhzaU1hcC5wdXQoIj8iLCAiXFw/Iik7CiAgICAgICAgZXNjYXBlWHNpTWFwLnB1dCgiWyIsICJcXFsiKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCIjIiwgIlxcIyIpOwogICAgICAgIGVzY2FwZVhzaU1hcC5wdXQoIn4iLCAiXFx+Iik7CiAgICAgICAgZXNjYXBlWHNpTWFwLnB1dCgiPSIsICJcXD0iKTsKICAgICAgICBlc2NhcGVYc2lNYXAucHV0KCIlIiwgIlxcJSIpOwogICAgICAgIEVTQ0FQRV9YU0kgPSBuZXcgTG9va3VwVHJhbnNsYXRvcigKICAgICAgICAgICAgICAgIENvbGxlY3Rpb25zLnVubW9kaWZpYWJsZU1hcChlc2NhcGVYc2lNYXApCiAgICAgICAgKTsKICAgIH0KCiAgICAvKiBVTkVTQ0FQRSBUUkFOU0xBVE9SUyAqLwoKICAgIC8qKgogICAgICogVHJhbnNsYXRvciBvYmplY3QgZm9yIHVuZXNjYXBpbmcgZXNjYXBlZCBKYXZhLiAKICAgICAqCiAgICAgKiBXaGlsZSB7QGxpbmsgI3VuZXNjYXBlSmF2YShTdHJpbmcpfSBpcyB0aGUgZXhwZWN0ZWQgbWV0aG9kIG9mIHVzZSwgdGhpcyAKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIEphdmEgdW5lc2NhcGluZyBmdW5jdGlvbmFsaXR5IHRvIGJlIHVzZWQgCiAgICAgKiBhcyB0aGUgZm91bmRhdGlvbiBmb3IgYSBjdXN0b20gdHJhbnNsYXRvci4KICAgICAqLwogICAgLy8gVE9ETzogdGhyb3cgImlsbGVnYWwgY2hhcmFjdGVyOiBcOTIiIGFzIGFuIEV4Y2VwdGlvbiBpZiBhIFwgb24gdGhlIGVuZCBvZiB0aGUgSmF2YSAoYXMgcGVyIHRoZSBjb21waWxlcik/CiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgVU5FU0NBUEVfSkFWQTsKICAgIHN0YXRpYyB7CiAgICAgICAgTWFwPENoYXJTZXF1ZW5jZSwgQ2hhclNlcXVlbmNlPiB1bmVzY2FwZUphdmFNYXAgPSBuZXcgSGFzaE1hcDw+KCk7CiAgICAgICAgdW5lc2NhcGVKYXZhTWFwLnB1dCgiXFxcXCIsICJcXCIpOwogICAgICAgIHVuZXNjYXBlSmF2YU1hcC5wdXQoIlxcXCIiLCAiXCIiKTsKICAgICAgICB1bmVzY2FwZUphdmFNYXAucHV0KCJcXCciLCAiJyIpOwogICAgICAgIHVuZXNjYXBlSmF2YU1hcC5wdXQoIlxcIiwgIiIpOwogICAgICAgIFVORVNDQVBFX0pBVkEgPSBuZXcgQWdncmVnYXRlVHJhbnNsYXRvcigKICAgICAgICAgICAgICAgIG5ldyBPY3RhbFVuZXNjYXBlcigpLCAgICAgLy8gLmJldHdlZW4oJ1wxJywgJ1wzNzcnKSwKICAgICAgICAgICAgICAgIG5ldyBVbmljb2RlVW5lc2NhcGVyKCksCiAgICAgICAgICAgICAgICBuZXcgTG9va3VwVHJhbnNsYXRvcihFbnRpdHlBcnJheXMuSkFWQV9DVFJMX0NIQVJTX1VORVNDQVBFKSwKICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKENvbGxlY3Rpb25zLnVubW9kaWZpYWJsZU1hcCh1bmVzY2FwZUphdmFNYXApKQogICAgICAgICk7CiAgICB9CgogICAgLyoqCiAgICAgKiBUcmFuc2xhdG9yIG9iamVjdCBmb3IgdW5lc2NhcGluZyBlc2NhcGVkIEVjbWFTY3JpcHQuIAogICAgICoKICAgICAqIFdoaWxlIHtAbGluayAjdW5lc2NhcGVFY21hU2NyaXB0KFN0cmluZyl9IGlzIHRoZSBleHBlY3RlZCBtZXRob2Qgb2YgdXNlLCB0aGlzIAogICAgICogb2JqZWN0IGFsbG93cyB0aGUgRWNtYVNjcmlwdCB1bmVzY2FwaW5nIGZ1bmN0aW9uYWxpdHkgdG8gYmUgdXNlZCAKICAgICAqIGFzIHRoZSBmb3VuZGF0aW9uIGZvciBhIGN1c3RvbSB0cmFuc2xhdG9yLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgVU5FU0NBUEVfRUNNQVNDUklQVCA9IFVORVNDQVBFX0pBVkE7CgogICAgLyoqCiAgICAgKiBUcmFuc2xhdG9yIG9iamVjdCBmb3IgdW5lc2NhcGluZyBlc2NhcGVkIEpzb24uCiAgICAgKgogICAgICogV2hpbGUge0BsaW5rICN1bmVzY2FwZUpzb24oU3RyaW5nKX0gaXMgdGhlIGV4cGVjdGVkIG1ldGhvZCBvZiB1c2UsIHRoaXMKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIEpzb24gdW5lc2NhcGluZyBmdW5jdGlvbmFsaXR5IHRvIGJlIHVzZWQKICAgICAqIGFzIHRoZSBmb3VuZGF0aW9uIGZvciBhIGN1c3RvbSB0cmFuc2xhdG9yLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgVU5FU0NBUEVfSlNPTiA9IFVORVNDQVBFX0pBVkE7CgogICAgLyoqCiAgICAgKiBUcmFuc2xhdG9yIG9iamVjdCBmb3IgdW5lc2NhcGluZyBlc2NhcGVkIEhUTUwgMy4wLiAKICAgICAqCiAgICAgKiBXaGlsZSB7QGxpbmsgI3VuZXNjYXBlSHRtbDMoU3RyaW5nKX0gaXMgdGhlIGV4cGVjdGVkIG1ldGhvZCBvZiB1c2UsIHRoaXMgCiAgICAgKiBvYmplY3QgYWxsb3dzIHRoZSBIVE1MIHVuZXNjYXBpbmcgZnVuY3Rpb25hbGl0eSB0byBiZSB1c2VkIAogICAgICogYXMgdGhlIGZvdW5kYXRpb24gZm9yIGEgY3VzdG9tIHRyYW5zbGF0b3IuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciBVTkVTQ0FQRV9IVE1MMyA9CiAgICAgICAgICAgIG5ldyBBZ2dyZWdhdGVUcmFuc2xhdG9yKAogICAgICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKEVudGl0eUFycmF5cy5CQVNJQ19VTkVTQ0FQRSksCiAgICAgICAgICAgICAgICAgICAgbmV3IExvb2t1cFRyYW5zbGF0b3IoRW50aXR5QXJyYXlzLklTTzg4NTlfMV9VTkVTQ0FQRSksCiAgICAgICAgICAgICAgICAgICAgbmV3IE51bWVyaWNFbnRpdHlVbmVzY2FwZXIoKQogICAgICAgICAgICApOwoKICAgIC8qKgogICAgICogVHJhbnNsYXRvciBvYmplY3QgZm9yIHVuZXNjYXBpbmcgZXNjYXBlZCBIVE1MIDQuMC4gCiAgICAgKgogICAgICogV2hpbGUge0BsaW5rICN1bmVzY2FwZUh0bWw0KFN0cmluZyl9IGlzIHRoZSBleHBlY3RlZCBtZXRob2Qgb2YgdXNlLCB0aGlzIAogICAgICogb2JqZWN0IGFsbG93cyB0aGUgSFRNTCB1bmVzY2FwaW5nIGZ1bmN0aW9uYWxpdHkgdG8gYmUgdXNlZCAKICAgICAqIGFzIHRoZSBmb3VuZGF0aW9uIGZvciBhIGN1c3RvbSB0cmFuc2xhdG9yLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgVU5FU0NBUEVfSFRNTDQgPQogICAgICAgICAgICBuZXcgQWdncmVnYXRlVHJhbnNsYXRvcigKICAgICAgICAgICAgICAgICAgICBuZXcgTG9va3VwVHJhbnNsYXRvcihFbnRpdHlBcnJheXMuQkFTSUNfVU5FU0NBUEUpLAogICAgICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKEVudGl0eUFycmF5cy5JU084ODU5XzFfVU5FU0NBUEUpLAogICAgICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKEVudGl0eUFycmF5cy5IVE1MNDBfRVhURU5ERURfVU5FU0NBUEUpLAogICAgICAgICAgICAgICAgICAgIG5ldyBOdW1lcmljRW50aXR5VW5lc2NhcGVyKCkKICAgICAgICAgICAgKTsKCiAgICAvKioKICAgICAqIFRyYW5zbGF0b3Igb2JqZWN0IGZvciB1bmVzY2FwaW5nIGVzY2FwZWQgWE1MLgogICAgICoKICAgICAqIFdoaWxlIHtAbGluayAjdW5lc2NhcGVYbWwoU3RyaW5nKX0gaXMgdGhlIGV4cGVjdGVkIG1ldGhvZCBvZiB1c2UsIHRoaXMgCiAgICAgKiBvYmplY3QgYWxsb3dzIHRoZSBYTUwgdW5lc2NhcGluZyBmdW5jdGlvbmFsaXR5IHRvIGJlIHVzZWQgCiAgICAgKiBhcyB0aGUgZm91bmRhdGlvbiBmb3IgYSBjdXN0b20gdHJhbnNsYXRvci4KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBDaGFyU2VxdWVuY2VUcmFuc2xhdG9yIFVORVNDQVBFX1hNTCA9CiAgICAgICAgICAgIG5ldyBBZ2dyZWdhdGVUcmFuc2xhdG9yKAogICAgICAgICAgICAgICAgICAgIG5ldyBMb29rdXBUcmFuc2xhdG9yKEVudGl0eUFycmF5cy5CQVNJQ19VTkVTQ0FQRSksCiAgICAgICAgICAgICAgICAgICAgbmV3IExvb2t1cFRyYW5zbGF0b3IoRW50aXR5QXJyYXlzLkFQT1NfVU5FU0NBUEUpLAogICAgICAgICAgICAgICAgICAgIG5ldyBOdW1lcmljRW50aXR5VW5lc2NhcGVyKCkKICAgICAgICAgICAgKTsKCiAgICAvKioKICAgICAqIFRyYW5zbGF0b3Igb2JqZWN0IGZvciB1bmVzY2FwaW5nIGVzY2FwZWQgQ29tbWEgU2VwYXJhdGVkIFZhbHVlIGVudHJpZXMuCiAgICAgKgogICAgICogV2hpbGUge0BsaW5rICN1bmVzY2FwZUNzdihTdHJpbmcpfSBpcyB0aGUgZXhwZWN0ZWQgbWV0aG9kIG9mIHVzZSwgdGhpcyAKICAgICAqIG9iamVjdCBhbGxvd3MgdGhlIENTViB1bmVzY2FwaW5nIGZ1bmN0aW9uYWxpdHkgdG8gYmUgdXNlZCAKICAgICAqIGFzIHRoZSBmb3VuZGF0aW9uIGZvciBhIGN1c3RvbSB0cmFuc2xhdG9yLgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgVU5FU0NBUEVfQ1NWID0gbmV3IENzdlRyYW5zbGF0b3JzLkNzdlVuZXNjYXBlcigpOwoKICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciBVTkVTQ0FQRV9YU0kgPSBuZXcgWHNpVW5lc2NhcGVyKCk7CgogICAgLyoqCiAgICAgKiBUcmFuc2xhdG9yIG9iamVjdCBmb3IgdW5lc2NhcGluZyBiYWNrc2xhc2ggZXNjYXBlZCBlbnRyaWVzLgogICAgICovCiAgICBzdGF0aWMgY2xhc3MgWHNpVW5lc2NhcGVyIGV4dGVuZHMgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciB7CgogICAgICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIGNoYXIgQkFDS1NMQVNIID0gJ1xcJzsKCiAgICAgICAgQE92ZXJyaWRlCiAgICAgICAgcHVibGljIGludCB0cmFuc2xhdGUoZmluYWwgQ2hhclNlcXVlbmNlIGlucHV0LCBmaW5hbCBpbnQgaW5kZXgsIGZpbmFsIFdyaXRlciBvdXQpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgogICAgICAgICAgICBpZihpbmRleCAhPSAwKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJYc2lVbmVzY2FwZXIgc2hvdWxkIG5ldmVyIHJlYWNoIHRoZSBbMV0gaW5kZXgiKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgU3RyaW5nIHMgPSBpbnB1dC50b1N0cmluZygpOwoKICAgICAgICAgICAgaW50IHNlZ21lbnRTdGFydCA9IDA7CiAgICAgICAgICAgIGludCBzZWFyY2hPZmZzZXQgPSAwOwogICAgICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICAgICAgaW50IHBvcyA9IHMuaW5kZXhPZihCQUNLU0xBU0gsIHNlYXJjaE9mZnNldCk7CiAgICAgICAgICAgICAgICBpZiAocG9zID09IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHNlZ21lbnRTdGFydCA8IHMubGVuZ3RoKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgb3V0LndyaXRlKHMuc3Vic3RyaW5nKHNlZ21lbnRTdGFydCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChwb3MgPiBzZWdtZW50U3RhcnQpIHsKICAgICAgICAgICAgICAgICAgICBvdXQud3JpdGUocy5zdWJzdHJpbmcoc2VnbWVudFN0YXJ0LCBwb3MpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHNlZ21lbnRTdGFydCA9IHBvcyArIDE7CiAgICAgICAgICAgICAgICBzZWFyY2hPZmZzZXQgPSBwb3MgKyAyOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gQ2hhcmFjdGVyLmNvZGVQb2ludENvdW50KGlucHV0LCAwLCBpbnB1dC5sZW5ndGgoKSk7CiAgICAgICAgfQogICAgfQoKICAgIC8qIEhlbHBlciBmdW5jdGlvbnMgKi8KCiAgICAvKioKICAgICAqIDxwPntAY29kZSBTdHJpbmdFc2NhcGVVdGlsc30gaW5zdGFuY2VzIHNob3VsZCBOT1QgYmUgY29uc3RydWN0ZWQgaW4KICAgICAqIHN0YW5kYXJkIHByb2dyYW1taW5nLjwvcD4KICAgICAqCiAgICAgKiA8cD5JbnN0ZWFkLCB0aGUgY2xhc3Mgc2hvdWxkIGJlIHVzZWQgYXM6PC9wPgogICAgICogPHByZT5TdHJpbmdFc2NhcGVVdGlscy5lc2NhcGVKYXZhKCJmb28iKTs8L3ByZT4KICAgICAqCiAgICAgKiA8cD5UaGlzIGNvbnN0cnVjdG9yIGlzIHB1YmxpYyB0byBwZXJtaXQgdG9vbHMgdGhhdCByZXF1aXJlIGEgSmF2YUJlYW4KICAgICAqIGluc3RhbmNlIHRvIG9wZXJhdGUuPC9wPgogICAgICovCiAgICBwdWJsaWMgU3RyaW5nRXNjYXBlVXRpbHMoKSB7CiAgICAgICAgc3VwZXIoKTsKICAgIH0KCiAgICAvKioKICAgICAqIDxwPkNvbnZlbmllbmNlIHdyYXBwZXIgZm9yIHtAbGluayBqYXZhLmxhbmcuU3RyaW5nQnVpbGRlcn0gcHJvdmlkaW5nIGVzY2FwZSBtZXRob2RzLjwvcD4KICAgICAqCiAgICAgKiA8cD5FeGFtcGxlOjwvcD4KICAgICAqIDxwcmU+CiAgICAgKiBuZXcgQnVpbGRlcihFU0NBUEVfSFRNTDQpCiAgICAgKiAgICAgIC5hcHBlbmQoIiZsdDtwJmd0OyIpCiAgICAgKiAgICAgIC5lc2NhcGUoIlRoaXMgaXMgcGFyYWdyYXBoIDEgYW5kIHNwZWNpYWwgY2hhcnMgbGlrZSAmYW1wOyBnZXQgZXNjYXBlZC4iKQogICAgICogICAgICAuYXBwZW5kKCImbHQ7L3AmZ3Q7Jmx0O3AmZ3Q7IikKICAgICAqICAgICAgLmVzY2FwZSgiVGhpcyBpcyBwYXJhZ3JhcGggMiAmYW1wOyBtb3JlLi4uIikKICAgICAqICAgICAgLmFwcGVuZCgiJmx0Oy9wJmd0OyIpCiAgICAgKiAgICAgIC50b1N0cmluZygpCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgY2xhc3MgQnVpbGRlciB7CgogICAgICAgIHByaXZhdGUgZmluYWwgU3RyaW5nQnVpbGRlciBzYjsKICAgICAgICBwcml2YXRlIGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgdHJhbnNsYXRvcjsKCiAgICAgICAgcHJpdmF0ZSBCdWlsZGVyKGZpbmFsIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3IgdHJhbnNsYXRvcikgewogICAgICAgICAgICB0aGlzLnNiID0gbmV3IFN0cmluZ0J1aWxkZXIoKTsKICAgICAgICAgICAgdGhpcy50cmFuc2xhdG9yID0gdHJhbnNsYXRvcjsKICAgICAgICB9CgogICAgICAgIC8qKgogICAgICAgICAqIDxwPkVzY2FwZSB7QGNvZGUgaW5wdXR9IGFjY29yZGluZyB0byB0aGUgZ2l2ZW4ge0BsaW5rIENoYXJTZXF1ZW5jZVRyYW5zbGF0b3J9LjwvcD4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBpbnB1dCB0aGUgU3RyaW5nIHRvIGVzY2FwZQogICAgICAgICAqIEByZXR1cm4ge0Bjb2RlIHRoaXN9LCB0byBlbmFibGUgY2hhaW5pbmcKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgQnVpbGRlciBlc2NhcGUoZmluYWwgU3RyaW5nIGlucHV0KSB7CiAgICAgICAgICAgIHNiLmFwcGVuZCh0cmFuc2xhdG9yLnRyYW5zbGF0ZShpbnB1dCkpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CgogICAgICAgIC8qKgogICAgICAgICAqIExpdGVyYWwgYXBwZW5kLCBubyBlc2NhcGluZyBiZWluZyBkb25lLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGlucHV0IHRoZSBTdHJpbmcgdG8gYXBwZW5kCiAgICAgICAgICogQHJldHVybiB7QGNvZGUgdGhpc30sIHRvIGVuYWJsZSBjaGFpbmluZwogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBCdWlsZGVyIGFwcGVuZChmaW5hbCBTdHJpbmcgaW5wdXQpIHsKICAgICAgICAgICAgc2IuYXBwZW5kKGlucHV0KTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQoKICAgICAgICAvKioKICAgICAgICAgKiA8cD5SZXR1cm4gdGhlIGVzY2FwZWQgc3RyaW5nLjwvcD4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gdGhlIGVzY2FwZWQgc3RyaW5nCiAgICAgICAgICovCiAgICAgICAgQE92ZXJyaWRlCiAgICAgICAgcHVibGljIFN0cmluZyB0b1N0cmluZygpIHsKICAgICAgICAgICAgcmV0dXJuIHNiLnRvU3RyaW5nKCk7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogR2V0IGEge0BsaW5rIEJ1aWxkZXJ9LgogICAgICogQHBhcmFtIHRyYW5zbGF0b3IgdGhlIHRleHQgdHJhbnNsYXRvcgogICAgICogQHJldHVybiB7QGxpbmsgQnVpbGRlcn0KICAgICAqLwogICAgcHVibGljIHN0YXRpYyBTdHJpbmdFc2NhcGVVdGlscy5CdWlsZGVyIGJ1aWxkZXIoZmluYWwgQ2hhclNlcXVlbmNlVHJhbnNsYXRvciB0cmFuc2xhdG9yKSB7CiAgICAgICAgcmV0dXJuIG5ldyBCdWlsZGVyKHRyYW5zbGF0b3IpOwogICAgfQoKICAgIC8vIEphdmEgYW5kIEphdmFTY3JpcHQKICAgIC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgIC8qKgogICAgICogPHA+RXNjYXBlcyB0aGUgY2hhcmFjdGVycyBpbiBhIHtAY29kZSBTdHJpbmd9IHVzaW5nIEphdmEgU3RyaW5nIHJ1bGVzLjwvcD4KICAgICAqCiAgICAgKiA8cD5EZWFscyBjb3JyZWN0bHkgd2l0aCBxdW90ZXMgYW5kIGNvbnRyb2wtY2hhcnMgKHRhYiwgYmFja3NsYXNoLCBjciwgZmYsIGV0Yy4pIDwvcD4KICAgICAqCiAgICAgKiA8cD5TbyBhIHRhYiBiZWNvbWVzIHRoZSBjaGFyYWN0ZXJzIHtAY29kZSAnXFwnfSBhbmQKICAgICAqIHtAY29kZSAndCd9LjwvcD4KICAgICAqCiAgICAgKiA8cD5UaGUgb25seSBkaWZmZXJlbmNlIGJldHdlZW4gSmF2YSBzdHJpbmdzIGFuZCBKYXZhU2NyaXB0IHN0cmluZ3MKICAgICAqIGlzIHRoYXQgaW4gSmF2YVNjcmlwdCwgYSBzaW5nbGUgcXVvdGUgYW5kIGZvcndhcmQtc2xhc2ggKC8pIGFyZSBlc2NhcGVkLjwvcD4KICAgICAqCiAgICAgKiA8cD5FeGFtcGxlOjwvcD4KICAgICAqIDxwcmU+CiAgICAgKiBpbnB1dCBzdHJpbmc6IEhlIGRpZG4ndCBzYXksICJTdG9wISIKICAgICAqIG91dHB1dCBzdHJpbmc6IEhlIGRpZG4ndCBzYXksIFwiU3RvcCFcIgogICAgICogPC9wcmU+CiAgICAgKgogICAgICogQHBhcmFtIGlucHV0ICBTdHJpbmcgdG8gZXNjYXBlIHZhbHVlcyBpbiwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gU3RyaW5nIHdpdGggZXNjYXBlZCB2YWx1ZXMsIHtAY29kZSBudWxsfSBpZiBudWxsIHN0cmluZyBpbnB1dAogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBlc2NhcGVKYXZhKGZpbmFsIFN0cmluZyBpbnB1dCkgewogICAgICAgIHJldHVybiBFU0NBUEVfSkFWQS50cmFuc2xhdGUoaW5wdXQpOwogICAgfQoKICAgIC8qKgogICAgICogPHA+RXNjYXBlcyB0aGUgY2hhcmFjdGVycyBpbiBhIHtAY29kZSBTdHJpbmd9IHVzaW5nIEVjbWFTY3JpcHQgU3RyaW5nIHJ1bGVzLjwvcD4KICAgICAqIDxwPkVzY2FwZXMgYW55IHZhbHVlcyBpdCBmaW5kcyBpbnRvIHRoZWlyIEVjbWFTY3JpcHQgU3RyaW5nIGZvcm0uCiAgICAgKiBEZWFscyBjb3JyZWN0bHkgd2l0aCBxdW90ZXMgYW5kIGNvbnRyb2wtY2hhcnMgKHRhYiwgYmFja3NsYXNoLCBjciwgZmYsIGV0Yy4pIDwvcD4KICAgICAqCiAgICAgKiA8cD5TbyBhIHRhYiBiZWNvbWVzIHRoZSBjaGFyYWN0ZXJzIHtAY29kZSAnXFwnfSBhbmQKICAgICAqIHtAY29kZSAndCd9LjwvcD4KICAgICAqCiAgICAgKiA8cD5UaGUgb25seSBkaWZmZXJlbmNlIGJldHdlZW4gSmF2YSBzdHJpbmdzIGFuZCBFY21hU2NyaXB0IHN0cmluZ3MKICAgICAqIGlzIHRoYXQgaW4gRWNtYVNjcmlwdCwgYSBzaW5nbGUgcXVvdGUgYW5kIGZvcndhcmQtc2xhc2ggKC8pIGFyZSBlc2NhcGVkLjwvcD4KICAgICAqCiAgICAgKiA8cD5Ob3RlIHRoYXQgRWNtYVNjcmlwdCBpcyBiZXN0IGtub3duIGJ5IHRoZSBKYXZhU2NyaXB0IGFuZCBBY3Rpb25TY3JpcHQgZGlhbGVjdHMuIDwvcD4KICAgICAqCiAgICAgKiA8cD5FeGFtcGxlOjwvcD4KICAgICAqIDxwcmU+CiAgICAgKiBpbnB1dCBzdHJpbmc6IEhlIGRpZG4ndCBzYXksICJTdG9wISIKICAgICAqIG91dHB1dCBzdHJpbmc6IEhlIGRpZG5cJ3Qgc2F5LCBcIlN0b3AhXCIKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIDxiPlNlY3VyaXR5IE5vdGUuPC9iPiBXZSBvbmx5IHByb3ZpZGUgYmFja3NsYXNoIGVzY2FwaW5nIGluIHRoaXMgbWV0aG9kLiBGb3IgZXhhbXBsZSwge0Bjb2RlICdcIid9IGhhcyB0aGUgb3V0cHV0CiAgICAgKiB7QGNvZGUgJ1xcXCInfSB3aGljaCBjb3VsZCByZXN1bHQgaW4gcG90ZW50aWFsIGlzc3VlcyBpbiB0aGUgY2FzZSB3aGVyZSB0aGUgc3RyaW5nIGJlaW5nIGVzY2FwZWQgaXMgYmVpbmcgdXNlZAogICAgICogaW4gYW4gSFRNTCB0YWcgbGlrZSB7QGNvZGUgPHNlbGVjdCBvbm1vdXNlb3Zlcj0iLi4uIiAvPn0uIElmIHlvdSB3aXNoIHRvIGhhdmUgbW9yZSByaWdvcm91cyBzdHJpbmcgZXNjYXBpbmcsIHlvdQogICAgICogbWF5IGNvbnNpZGVyIHRoZQogICAgICogPGEgaHJlZj0iaHR0cHM6Ly93d3cub3dhc3Aub3JnL2luZGV4LnBocC9DYXRlZ29yeTpPV0FTUF9FbnRlcnByaXNlX1NlY3VyaXR5X0FQSV9KQVZBIj5FU0FQSSBMaWJyYXJpZXM8L2E+LiBGdXJ0aGVyLAogICAgICogeW91IGNhbiB2aWV3IHRoZQogICAgICogPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL2VzYXBpIj5FU0FQSSBHaXRIdWIgT3JnPC9hPi4KICAgICAqCiAgICAgKiBAcGFyYW0gaW5wdXQgIFN0cmluZyB0byBlc2NhcGUgdmFsdWVzIGluLCBtYXkgYmUgbnVsbAogICAgICogQHJldHVybiBTdHJpbmcgd2l0aCBlc2NhcGVkIHZhbHVlcywge0Bjb2RlIG51bGx9IGlmIG51bGwgc3RyaW5nIGlucHV0CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgU3RyaW5nIGVzY2FwZUVjbWFTY3JpcHQoZmluYWwgU3RyaW5nIGlucHV0KSB7CiAgICAgICAgcmV0dXJuIEVTQ0FQRV9FQ01BU0NSSVBULnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgogICAgLyoqCiAgICAgKiA8cD5Fc2NhcGVzIHRoZSBjaGFyYWN0ZXJzIGluIGEge0Bjb2RlIFN0cmluZ30gdXNpbmcgSnNvbiBTdHJpbmcgcnVsZXMuPC9wPgogICAgICogPHA+RXNjYXBlcyBhbnkgdmFsdWVzIGl0IGZpbmRzIGludG8gdGhlaXIgSnNvbiBTdHJpbmcgZm9ybS4KICAgICAqIERlYWxzIGNvcnJlY3RseSB3aXRoIHF1b3RlcyBhbmQgY29udHJvbC1jaGFycyAodGFiLCBiYWNrc2xhc2gsIGNyLCBmZiwgZXRjLikgPC9wPgogICAgICoKICAgICAqIDxwPlNvIGEgdGFiIGJlY29tZXMgdGhlIGNoYXJhY3RlcnMge0Bjb2RlICdcXCd9IGFuZAogICAgICoge0Bjb2RlICd0J30uPC9wPgogICAgICoKICAgICAqIDxwPlRoZSBvbmx5IGRpZmZlcmVuY2UgYmV0d2VlbiBKYXZhIHN0cmluZ3MgYW5kIEpzb24gc3RyaW5ncwogICAgICogaXMgdGhhdCBpbiBKc29uLCBmb3J3YXJkLXNsYXNoICgvKSBpcyBlc2NhcGVkLjwvcD4KICAgICAqCiAgICAgKiA8cD5TZWUgaHR0cDovL3d3dy5pZXRmLm9yZy9yZmMvcmZjNDYyNy50eHQgZm9yIGZ1cnRoZXIgZGV0YWlscy4gPC9wPgogICAgICoKICAgICAqIDxwPkV4YW1wbGU6PC9wPgogICAgICogPHByZT4KICAgICAqIGlucHV0IHN0cmluZzogSGUgZGlkbid0IHNheSwgIlN0b3AhIgogICAgICogb3V0cHV0IHN0cmluZzogSGUgZGlkbid0IHNheSwgXCJTdG9wIVwiCiAgICAgKiA8L3ByZT4KICAgICAqCiAgICAgKiBAcGFyYW0gaW5wdXQgIFN0cmluZyB0byBlc2NhcGUgdmFsdWVzIGluLCBtYXkgYmUgbnVsbAogICAgICogQHJldHVybiBTdHJpbmcgd2l0aCBlc2NhcGVkIHZhbHVlcywge0Bjb2RlIG51bGx9IGlmIG51bGwgc3RyaW5nIGlucHV0CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgU3RyaW5nIGVzY2FwZUpzb24oZmluYWwgU3RyaW5nIGlucHV0KSB7CiAgICAgICAgcmV0dXJuIEVTQ0FQRV9KU09OLnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgogICAgLyoqCiAgICAgKiA8cD5VbmVzY2FwZXMgYW55IEphdmEgbGl0ZXJhbHMgZm91bmQgaW4gdGhlIHtAY29kZSBTdHJpbmd9LgogICAgICogRm9yIGV4YW1wbGUsIGl0IHdpbGwgdHVybiBhIHNlcXVlbmNlIG9mIHtAY29kZSAnXCd9IGFuZAogICAgICoge0Bjb2RlICduJ30gaW50byBhIG5ld2xpbmUgY2hhcmFjdGVyLCB1bmxlc3MgdGhlIHtAY29kZSAnXCd9CiAgICAgKiBpcyBwcmVjZWRlZCBieSBhbm90aGVyIHtAY29kZSAnXCd9LjwvcD4KICAgICAqCiAgICAgKiBAcGFyYW0gaW5wdXQgIHRoZSB7QGNvZGUgU3RyaW5nfSB0byB1bmVzY2FwZSwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gYSBuZXcgdW5lc2NhcGVkIHtAY29kZSBTdHJpbmd9LCB7QGNvZGUgbnVsbH0gaWYgbnVsbCBzdHJpbmcgaW5wdXQKICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBTdHJpbmcgdW5lc2NhcGVKYXZhKGZpbmFsIFN0cmluZyBpbnB1dCkgewogICAgICAgIHJldHVybiBVTkVTQ0FQRV9KQVZBLnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgogICAgLyoqCiAgICAgKiA8cD5VbmVzY2FwZXMgYW55IEVjbWFTY3JpcHQgbGl0ZXJhbHMgZm91bmQgaW4gdGhlIHtAY29kZSBTdHJpbmd9LjwvcD4KICAgICAqCiAgICAgKiA8cD5Gb3IgZXhhbXBsZSwgaXQgd2lsbCB0dXJuIGEgc2VxdWVuY2Ugb2Yge0Bjb2RlICdcJ30gYW5kIHtAY29kZSAnbid9CiAgICAgKiBpbnRvIGEgbmV3bGluZSBjaGFyYWN0ZXIsIHVubGVzcyB0aGUge0Bjb2RlICdcJ30gaXMgcHJlY2VkZWQgYnkgYW5vdGhlcgogICAgICoge0Bjb2RlICdcJ30uPC9wPgogICAgICoKICAgICAqIEBzZWUgI3VuZXNjYXBlSmF2YShTdHJpbmcpCiAgICAgKiBAcGFyYW0gaW5wdXQgIHRoZSB7QGNvZGUgU3RyaW5nfSB0byB1bmVzY2FwZSwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gQSBuZXcgdW5lc2NhcGVkIHtAY29kZSBTdHJpbmd9LCB7QGNvZGUgbnVsbH0gaWYgbnVsbCBzdHJpbmcgaW5wdXQKICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBTdHJpbmcgdW5lc2NhcGVFY21hU2NyaXB0KGZpbmFsIFN0cmluZyBpbnB1dCkgewogICAgICAgIHJldHVybiBVTkVTQ0FQRV9FQ01BU0NSSVBULnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgogICAgLyoqCiAgICAgKiA8cD5VbmVzY2FwZXMgYW55IEpzb24gbGl0ZXJhbHMgZm91bmQgaW4gdGhlIHtAY29kZSBTdHJpbmd9LjwvcD4KICAgICAqCiAgICAgKiA8cD5Gb3IgZXhhbXBsZSwgaXQgd2lsbCB0dXJuIGEgc2VxdWVuY2Ugb2Yge0Bjb2RlICdcJ30gYW5kIHtAY29kZSAnbid9CiAgICAgKiBpbnRvIGEgbmV3bGluZSBjaGFyYWN0ZXIsIHVubGVzcyB0aGUge0Bjb2RlICdcJ30gaXMgcHJlY2VkZWQgYnkgYW5vdGhlcgogICAgICoge0Bjb2RlICdcJ30uPC9wPgogICAgICoKICAgICAqIEBzZWUgI3VuZXNjYXBlSmF2YShTdHJpbmcpCiAgICAgKiBAcGFyYW0gaW5wdXQgIHRoZSB7QGNvZGUgU3RyaW5nfSB0byB1bmVzY2FwZSwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gQSBuZXcgdW5lc2NhcGVkIHtAY29kZSBTdHJpbmd9LCB7QGNvZGUgbnVsbH0gaWYgbnVsbCBzdHJpbmcgaW5wdXQKICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBTdHJpbmcgdW5lc2NhcGVKc29uKGZpbmFsIFN0cmluZyBpbnB1dCkgewogICAgICAgIHJldHVybiBVTkVTQ0FQRV9KU09OLnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgogICAgLy8gSFRNTCBhbmQgWE1MCiAgICAvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgICAvKioKICAgICAqIDxwPkVzY2FwZXMgdGhlIGNoYXJhY3RlcnMgaW4gYSB7QGNvZGUgU3RyaW5nfSB1c2luZyBIVE1MIGVudGl0aWVzLjwvcD4KICAgICAqCiAgICAgKiA8cD4KICAgICAqIEZvciBleGFtcGxlOgogICAgICogPC9wPiAKICAgICAqIDxwPjxjb2RlPiJicmVhZCIgJmFtcDsgImJ1dHRlciI8L2NvZGU+PC9wPgogICAgICogYmVjb21lczoKICAgICAqIDxwPgogICAgICogPGNvZGU+JmFtcDtxdW90O2JyZWFkJmFtcDtxdW90OyAmYW1wO2FtcDsgJmFtcDtxdW90O2J1dHRlciZhbXA7cXVvdDs8L2NvZGU+LgogICAgICogPC9wPgogICAgICoKICAgICAqIDxwPlN1cHBvcnRzIGFsbCBrbm93biBIVE1MIDQuMCBlbnRpdGllcywgaW5jbHVkaW5nIGZ1bmt5IGFjY2VudHMuCiAgICAgKiBOb3RlIHRoYXQgdGhlIGNvbW1vbmx5IHVzZWQgYXBvc3Ryb3BoZSBlc2NhcGUgY2hhcmFjdGVyICgmYW1wO2Fwb3M7KQogICAgICogaXMgbm90IGEgbGVnYWwgZW50aXR5IGFuZCBzbyBpcyBub3Qgc3VwcG9ydGVkKS4gPC9wPgogICAgICoKICAgICAqIEBwYXJhbSBpbnB1dCAgdGhlIHtAY29kZSBTdHJpbmd9IHRvIGVzY2FwZSwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gYSBuZXcgZXNjYXBlZCB7QGNvZGUgU3RyaW5nfSwge0Bjb2RlIG51bGx9IGlmIG51bGwgc3RyaW5nIGlucHV0CiAgICAgKgogICAgICogQHNlZSA8YSBocmVmPSJodHRwOi8vaG90d2lyZWQubHljb3MuY29tL3dlYm1vbmtleS9yZWZlcmVuY2Uvc3BlY2lhbF9jaGFyYWN0ZXJzLyI+SVNPIEVudGl0aWVzPC9hPgogICAgICogQHNlZSA8YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy9UUi9SRUMtaHRtbDMyI2xhdGluMSI+SFRNTCAzLjIgQ2hhcmFjdGVyIEVudGl0aWVzIGZvciBJU08gTGF0aW4tMTwvYT4KICAgICAqIEBzZWUgPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvUkVDLWh0bWw0MC9zZ21sL2VudGl0aWVzLmh0bWwiPkhUTUwgNC4wIENoYXJhY3RlciBlbnRpdHkgcmVmZXJlbmNlczwvYT4KICAgICAqIEBzZWUgPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQwMS9jaGFyc2V0Lmh0bWwjaC01LjMiPkhUTUwgNC4wMSBDaGFyYWN0ZXIgUmVmZXJlbmNlczwvYT4KICAgICAqIEBzZWUgPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQwMS9jaGFyc2V0Lmh0bWwjY29kZS1wb3NpdGlvbiI+SFRNTCA0LjAxIENvZGUgcG9zaXRpb25zPC9hPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBlc2NhcGVIdG1sNChmaW5hbCBTdHJpbmcgaW5wdXQpIHsKICAgICAgICByZXR1cm4gRVNDQVBFX0hUTUw0LnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgogICAgLyoqCiAgICAgKiA8cD5Fc2NhcGVzIHRoZSBjaGFyYWN0ZXJzIGluIGEge0Bjb2RlIFN0cmluZ30gdXNpbmcgSFRNTCBlbnRpdGllcy4KICAgICAqIEJ1dCBlc2NhcGVzIHRoZW0gb25seSBvbmNlLiBpLmUuIGRvZXMgbm90IGVzY2FwZSBhbHJlYWR5IGVzY2FwZWQgY2hhcmFjdGVycy48L3A+CiAgICAgKgogICAgICogPHA+CiAgICAgKiBGb3IgZXhhbXBsZToKICAgICAqIDwvcD4KICAgICAqIDxwPjxjb2RlPiJicmVhZCIgJmFtcDsgImJ1dHRlciI8L2NvZGU+PC9wPgogICAgICogYmVjb21lczoKICAgICAqIDxwPgogICAgICogPGNvZGU+JmFtcDtxdW90O2JyZWFkJmFtcDtxdW90OyAmYW1wO2FtcDsgJmFtcDtxdW90O2J1dHRlciZhbXA7cXVvdDs8L2NvZGU+LgogICAgICogPC9wPgogICAgICoKICAgICAqIDxwPgogICAgICogQnV0OgogICAgICogPC9wPgogICAgICogPHA+PGNvZGU+JmFtcDtxdW90O2JyZWFkJmFtcDtxdW90OyAmYW1wO2FtcDsgJmFtcDtxdW90O2J1dHRlciZhbXA7cXVvdDs8L2NvZGU+PC9wPgogICAgICogcmVtYWlucyB1bmFmZmVjdGVkLgogICAgICoKICAgICAqIDxwPlN1cHBvcnRzIGFsbCBrbm93biBIVE1MIDQuMCBlbnRpdGllcywgaW5jbHVkaW5nIGZ1bmt5IGFjY2VudHMuCiAgICAgKiBOb3RlIHRoYXQgdGhlIGNvbW1vbmx5IHVzZWQgYXBvc3Ryb3BoZSBlc2NhcGUgY2hhcmFjdGVyICgmYW1wO2Fwb3M7KQogICAgICogaXMgbm90IGEgbGVnYWwgZW50aXR5IGFuZCBzbyBpcyBub3Qgc3VwcG9ydGVkKS4gPC9wPgogICAgICoKICAgICAqIEBwYXJhbSBpbnB1dCAgdGhlIHtAY29kZSBTdHJpbmd9IHRvIGVzY2FwZSwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gYSBuZXcgZXNjYXBlZCB7QGNvZGUgU3RyaW5nfSwge0Bjb2RlIG51bGx9IGlmIG51bGwgc3RyaW5nIGlucHV0CiAgICAgKgogICAgICogQHNlZSA8YSBocmVmPSJodHRwOi8vaG90d2lyZWQubHljb3MuY29tL3dlYm1vbmtleS9yZWZlcmVuY2Uvc3BlY2lhbF9jaGFyYWN0ZXJzLyI+SVNPIEVudGl0aWVzPC9hPgogICAgICogQHNlZSA8YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy9UUi9SRUMtaHRtbDMyI2xhdGluMSI+SFRNTCAzLjIgQ2hhcmFjdGVyIEVudGl0aWVzIGZvciBJU08gTGF0aW4tMTwvYT4KICAgICAqIEBzZWUgPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvUkVDLWh0bWw0MC9zZ21sL2VudGl0aWVzLmh0bWwiPkhUTUwgNC4wIENoYXJhY3RlciBlbnRpdHkgcmVmZXJlbmNlczwvYT4KICAgICAqIEBzZWUgPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQwMS9jaGFyc2V0Lmh0bWwjaC01LjMiPkhUTUwgNC4wMSBDaGFyYWN0ZXIgUmVmZXJlbmNlczwvYT4KICAgICAqIEBzZWUgPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQwMS9jaGFyc2V0Lmh0bWwjY29kZS1wb3NpdGlvbiI+SFRNTCA0LjAxIENvZGUgcG9zaXRpb25zPC9hPgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBlc2NhcGVIdG1sNE9uY2UoZmluYWwgU3RyaW5nIGlucHV0KSB7CiAgICAgICAgcmV0dXJuIEVTQ0FQRV9IVE1MNF9PTkNFLnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgoKICAgIC8qKgogICAgICogPHA+RXNjYXBlcyB0aGUgY2hhcmFjdGVycyBpbiBhIHtAY29kZSBTdHJpbmd9IHVzaW5nIEhUTUwgZW50aXRpZXMuPC9wPgogICAgICogPHA+U3VwcG9ydHMgb25seSB0aGUgSFRNTCAzLjAgZW50aXRpZXMuIDwvcD4KICAgICAqCiAgICAgKiBAcGFyYW0gaW5wdXQgIHRoZSB7QGNvZGUgU3RyaW5nfSB0byBlc2NhcGUsIG1heSBiZSBudWxsCiAgICAgKiBAcmV0dXJuIGEgbmV3IGVzY2FwZWQge0Bjb2RlIFN0cmluZ30sIHtAY29kZSBudWxsfSBpZiBudWxsIHN0cmluZyBpbnB1dAogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBlc2NhcGVIdG1sMyhmaW5hbCBTdHJpbmcgaW5wdXQpIHsKICAgICAgICByZXR1cm4gRVNDQVBFX0hUTUwzLnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgogICAgLyoqCiAgICAgKiA8cD5Fc2NhcGVzIHRoZSBjaGFyYWN0ZXJzIGluIGEge0Bjb2RlIFN0cmluZ30gdXNpbmcgSFRNTCBlbnRpdGllcy4KICAgICAqIEJ1dCBlc2NhcGVzIHRoZW0gb25seSBvbmNlLiBpLmUuIGRvZXMgbm90IGVzY2FwZSBhbHJlYWR5IGVzY2FwZWQgY2hhcmFjdGVycy48L3A+CiAgICAgKiA8cD5TdXBwb3J0cyBvbmx5IHRoZSBIVE1MIDMuMCBlbnRpdGllcy4gPC9wPgogICAgICoKICAgICAqIEBwYXJhbSBpbnB1dCAgdGhlIHtAY29kZSBTdHJpbmd9IHRvIGVzY2FwZSwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gYSBuZXcgZXNjYXBlZCB7QGNvZGUgU3RyaW5nfSwge0Bjb2RlIG51bGx9IGlmIG51bGwgc3RyaW5nIGlucHV0CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgU3RyaW5nIGVzY2FwZUh0bWwzT25jZShmaW5hbCBTdHJpbmcgaW5wdXQpIHsKICAgICAgICByZXR1cm4gRVNDQVBFX0hUTUwzX09OQ0UudHJhbnNsYXRlKGlucHV0KTsKICAgIH0KCiAgICAvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgICAvKioKICAgICAqIDxwPlVuZXNjYXBlcyBhIHN0cmluZyBjb250YWluaW5nIGVudGl0eSBlc2NhcGVzIHRvIGEgc3RyaW5nCiAgICAgKiBjb250YWluaW5nIHRoZSBhY3R1YWwgVW5pY29kZSBjaGFyYWN0ZXJzIGNvcnJlc3BvbmRpbmcgdG8gdGhlCiAgICAgKiBlc2NhcGVzLiBTdXBwb3J0cyBIVE1MIDQuMCBlbnRpdGllcy48L3A+CiAgICAgKgogICAgICogPHA+Rm9yIGV4YW1wbGUsIHRoZSBzdHJpbmcge0Bjb2RlICImbHQ7RnJhbiZjY2VkaWw7YWlzJmd0OyJ9CiAgICAgKiB3aWxsIGJlY29tZSB7QGNvZGUgIjxGcmFu52Fpcz4ifTwvcD4KICAgICAqCiAgICAgKiA8cD5JZiBhbiBlbnRpdHkgaXMgdW5yZWNvZ25pemVkLCBpdCBpcyBsZWZ0IGFsb25lLCBhbmQgaW5zZXJ0ZWQKICAgICAqIHZlcmJhdGltIGludG8gdGhlIHJlc3VsdCBzdHJpbmcuIGUuZy4ge0Bjb2RlICImZ3Q7Jnp6eno7eCJ9IHdpbGwKICAgICAqIGJlY29tZSB7QGNvZGUgIj4menp6ejt4In0uPC9wPgogICAgICoKICAgICAqIEBwYXJhbSBpbnB1dCAgdGhlIHtAY29kZSBTdHJpbmd9IHRvIHVuZXNjYXBlLCBtYXkgYmUgbnVsbAogICAgICogQHJldHVybiBhIG5ldyB1bmVzY2FwZWQge0Bjb2RlIFN0cmluZ30sIHtAY29kZSBudWxsfSBpZiBudWxsIHN0cmluZyBpbnB1dAogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyB1bmVzY2FwZUh0bWw0KGZpbmFsIFN0cmluZyBpbnB1dCkgewogICAgICAgIHJldHVybiBVTkVTQ0FQRV9IVE1MNC50cmFuc2xhdGUoaW5wdXQpOwogICAgfQoKICAgIC8qKgogICAgICogPHA+VW5lc2NhcGVzIGEgc3RyaW5nIGNvbnRhaW5pbmcgZW50aXR5IGVzY2FwZXMgdG8gYSBzdHJpbmcKICAgICAqIGNvbnRhaW5pbmcgdGhlIGFjdHVhbCBVbmljb2RlIGNoYXJhY3RlcnMgY29ycmVzcG9uZGluZyB0byB0aGUKICAgICAqIGVzY2FwZXMuIFN1cHBvcnRzIG9ubHkgSFRNTCAzLjAgZW50aXRpZXMuPC9wPgogICAgICoKICAgICAqIEBwYXJhbSBpbnB1dCAgdGhlIHtAY29kZSBTdHJpbmd9IHRvIHVuZXNjYXBlLCBtYXkgYmUgbnVsbAogICAgICogQHJldHVybiBhIG5ldyB1bmVzY2FwZWQge0Bjb2RlIFN0cmluZ30sIHtAY29kZSBudWxsfSBpZiBudWxsIHN0cmluZyBpbnB1dAogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyB1bmVzY2FwZUh0bWwzKGZpbmFsIFN0cmluZyBpbnB1dCkgewogICAgICAgIHJldHVybiBVTkVTQ0FQRV9IVE1MMy50cmFuc2xhdGUoaW5wdXQpOwogICAgfQoKICAgIC8qKgogICAgICogPHA+RXNjYXBlcyB0aGUgY2hhcmFjdGVycyBpbiBhIHtAY29kZSBTdHJpbmd9IHVzaW5nIFhNTCBlbnRpdGllcy48L3A+CiAgICAgKgogICAgICogPHA+Rm9yIGV4YW1wbGU6IHtAY29kZSAiYnJlYWQiICYgImJ1dHRlciJ9ID0mZ3Q7CiAgICAgKiB7QGNvZGUgJnF1b3Q7YnJlYWQmcXVvdDsgJmFtcDsgJnF1b3Q7YnV0dGVyJnF1b3Q7fS4KICAgICAqIDwvcD4KICAgICAqCiAgICAgKiA8cD5Ob3RlIHRoYXQgWE1MIDEuMCBpcyBhIHRleHQtb25seSBmb3JtYXQ6IGl0IGNhbm5vdCByZXByZXNlbnQgY29udHJvbAogICAgICogY2hhcmFjdGVycyBvciB1bnBhaXJlZCBVbmljb2RlIHN1cnJvZ2F0ZSBjb2RlcG9pbnRzLCBldmVuIGFmdGVyIGVzY2FwaW5nLgogICAgICoge0Bjb2RlIGVzY2FwZVhtbDEwfSB3aWxsIHJlbW92ZSBjaGFyYWN0ZXJzIHRoYXQgZG8gbm90IGZpdCBpbiB0aGUKICAgICAqIGZvbGxvd2luZyByYW5nZXM6PC9wPgogICAgICoKICAgICAqIDxwPntAY29kZSAjeDkgfCAjeEEgfCAjeEQgfCBbI3gyMC0jeEQ3RkZdIHwgWyN4RTAwMC0jeEZGRkRdIHwgWyN4MTAwMDAtI3gxMEZGRkZdfTwvcD4KICAgICAqCiAgICAgKiA8cD5UaG91Z2ggbm90IHN0cmljdGx5IG5lY2Vzc2FyeSwge0Bjb2RlIGVzY2FwZVhtbDEwfSB3aWxsIGVzY2FwZQogICAgICogY2hhcmFjdGVycyBpbiB0aGUgZm9sbG93aW5nIHJhbmdlczo8L3A+CiAgICAgKgogICAgICogPHA+e0Bjb2RlIFsjeDdGLSN4ODRdIHwgWyN4ODYtI3g5Rl19PC9wPgogICAgICoKICAgICAqIDxwPlRoZSByZXR1cm5lZCBzdHJpbmcgY2FuIGJlIGluc2VydGVkIGludG8gYSB2YWxpZCBYTUwgMS4wIG9yIFhNTCAxLjEKICAgICAqIGRvY3VtZW50LiBJZiB5b3Ugd2FudCB0byBhbGxvdyBtb3JlIG5vbi10ZXh0IGNoYXJhY3RlcnMgaW4gYW4gWE1MIDEuMQogICAgICogZG9jdW1lbnQsIHVzZSB7QGxpbmsgI2VzY2FwZVhtbDExKFN0cmluZyl9LjwvcD4KICAgICAqCiAgICAgKiBAcGFyYW0gaW5wdXQgIHRoZSB7QGNvZGUgU3RyaW5nfSB0byBlc2NhcGUsIG1heSBiZSBudWxsCiAgICAgKiBAcmV0dXJuIGEgbmV3IGVzY2FwZWQge0Bjb2RlIFN0cmluZ30sIHtAY29kZSBudWxsfSBpZiBudWxsIHN0cmluZyBpbnB1dAogICAgICogQHNlZSAjdW5lc2NhcGVYbWwoamF2YS5sYW5nLlN0cmluZykKICAgICAqLwogICAgcHVibGljIHN0YXRpYyBTdHJpbmcgZXNjYXBlWG1sMTAoZmluYWwgU3RyaW5nIGlucHV0KSB7CiAgICAgICAgcmV0dXJuIEVTQ0FQRV9YTUwxMC50cmFuc2xhdGUoaW5wdXQpOwogICAgfQoKICAgIC8qKgogICAgICogPHA+RXNjYXBlcyB0aGUgY2hhcmFjdGVycyBpbiBhIHtAY29kZSBTdHJpbmd9IHVzaW5nIFhNTCBlbnRpdGllcy48L3A+CiAgICAgKgogICAgICogPHA+Rm9yIGV4YW1wbGU6IHtAY29kZSAiYnJlYWQiICYgImJ1dHRlciJ9ID0mZ3Q7CiAgICAgKiB7QGNvZGUgJnF1b3Q7YnJlYWQmcXVvdDsgJmFtcDsgJnF1b3Q7YnV0dGVyJnF1b3Q7fS4KICAgICAqIDwvcD4KICAgICAqCiAgICAgKiA8cD5YTUwgMS4xIGNhbiByZXByZXNlbnQgY2VydGFpbiBjb250cm9sIGNoYXJhY3RlcnMsIGJ1dCBpdCBjYW5ub3QgcmVwcmVzZW50CiAgICAgKiB0aGUgbnVsbCBieXRlIG9yIHVucGFpcmVkIFVuaWNvZGUgc3Vycm9nYXRlIGNvZGVwb2ludHMsIGV2ZW4gYWZ0ZXIgZXNjYXBpbmcuCiAgICAgKiB7QGNvZGUgZXNjYXBlWG1sMTF9IHdpbGwgcmVtb3ZlIGNoYXJhY3RlcnMgdGhhdCBkbyBub3QgZml0IGluIHRoZSBmb2xsb3dpbmcKICAgICAqIHJhbmdlczo8L3A+CiAgICAgKgogICAgICogPHA+e0Bjb2RlIFsjeDEtI3hEN0ZGXSB8IFsjeEUwMDAtI3hGRkZEXSB8IFsjeDEwMDAwLSN4MTBGRkZGXX08L3A+CiAgICAgKgogICAgICogPHA+e0Bjb2RlIGVzY2FwZVhtbDExfSB3aWxsIGVzY2FwZSBjaGFyYWN0ZXJzIGluIHRoZSBmb2xsb3dpbmcgcmFuZ2VzOjwvcD4KICAgICAqCiAgICAgKiA8cD57QGNvZGUgWyN4MS0jeDhdIHwgWyN4Qi0jeENdIHwgWyN4RS0jeDFGXSB8IFsjeDdGLSN4ODRdIHwgWyN4ODYtI3g5Rl19PC9wPgogICAgICoKICAgICAqIDxwPlRoZSByZXR1cm5lZCBzdHJpbmcgY2FuIGJlIGluc2VydGVkIGludG8gYSB2YWxpZCBYTUwgMS4xIGRvY3VtZW50LiBEbyBub3QKICAgICAqIHVzZSBpdCBmb3IgWE1MIDEuMCBkb2N1bWVudHMuPC9wPgogICAgICoKICAgICAqIEBwYXJhbSBpbnB1dCAgdGhlIHtAY29kZSBTdHJpbmd9IHRvIGVzY2FwZSwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gYSBuZXcgZXNjYXBlZCB7QGNvZGUgU3RyaW5nfSwge0Bjb2RlIG51bGx9IGlmIG51bGwgc3RyaW5nIGlucHV0CiAgICAgKiBAc2VlICN1bmVzY2FwZVhtbChqYXZhLmxhbmcuU3RyaW5nKQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIFN0cmluZyBlc2NhcGVYbWwxMShmaW5hbCBTdHJpbmcgaW5wdXQpIHsKICAgICAgICByZXR1cm4gRVNDQVBFX1hNTDExLnRyYW5zbGF0ZShpbnB1dCk7CiAgICB9CgogICAgLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgLyoqCiAgICAgKiA8cD5VbmVzY2FwZXMgYSBzdHJpbmcgY29udGFpbmluZyBYTUwgZW50aXR5IGVzY2FwZXMgdG8gYSBzdHJpbmcKICAgICAqIGNvbnRhaW5pbmcgdGhlIGFjdHVhbCBVbmljb2RlIGNoYXJhY3RlcnMgY29ycmVzcG9uZGluZyB0byB0aGUKICAgICAqIGVzY2FwZXMuPC9wPgogICAgICoKICAgICAqIDxwPlN1cHBvcnRzIG9ubHkgdGhlIGZpdmUgYmFzaWMgWE1MIGVudGl0aWVzIChndCwgbHQsIHF1b3QsIGFtcCwgYXBvcykuCiAgICAgKiBEb2VzIG5vdCBzdXBwb3J0IERURHMgb3IgZXh0ZXJuYWwgZW50aXRpZXMuPC9wPgogICAgICoKICAgICAqIDxwPk5vdGUgdGhhdCBudW1lcmljYWwgXFx1IFVuaWNvZGUgY29kZXMgYXJlIHVuZXNjYXBlZCB0byB0aGVpciByZXNwZWN0aXZlIAogICAgICogICAgVW5pY29kZSBjaGFyYWN0ZXJzLiBUaGlzIG1heSBjaGFuZ2UgaW4gZnV0dXJlIHJlbGVhc2VzLiA8L3A+CiAgICAgKgogICAgICogQHBhcmFtIGlucHV0ICB0aGUge0Bjb2RlIFN0cmluZ30gdG8gdW5lc2NhcGUsIG1heSBiZSBudWxsCiAgICAgKiBAcmV0dXJuIGEgbmV3IHVuZXNjYXBlZCB7QGNvZGUgU3RyaW5nfSwge0Bjb2RlIG51bGx9IGlmIG51bGwgc3RyaW5nIGlucHV0CiAgICAgKiBAc2VlICNlc2NhcGVYbWwxMChTdHJpbmcpCiAgICAgKiBAc2VlICNlc2NhcGVYbWwxMShTdHJpbmcpCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgU3RyaW5nIHVuZXNjYXBlWG1sKGZpbmFsIFN0cmluZyBpbnB1dCkgewogICAgICAgIHJldHVybiBVTkVTQ0FQRV9YTUwudHJhbnNsYXRlKGlucHV0KTsKICAgIH0KCiAgICAvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgogICAgLyoqCiAgICAgKiA8cD5SZXR1cm5zIGEge0Bjb2RlIFN0cmluZ30gdmFsdWUgZm9yIGEgQ1NWIGNvbHVtbiBlbmNsb3NlZCBpbiBkb3VibGUgcXVvdGVzLAogICAgICogaWYgcmVxdWlyZWQuPC9wPgogICAgICoKICAgICAqIDxwPklmIHRoZSB2YWx1ZSBjb250YWlucyBhIGNvbW1hLCBuZXdsaW5lIG9yIGRvdWJsZSBxdW90ZSwgdGhlbiB0aGUKICAgICAqICAgIFN0cmluZyB2YWx1ZSBpcyByZXR1cm5lZCBlbmNsb3NlZCBpbiBkb3VibGUgcXVvdGVzLjwvcD4KICAgICAqCiAgICAgKiA8cD5BbnkgZG91YmxlIHF1b3RlIGNoYXJhY3RlcnMgaW4gdGhlIHZhbHVlIGFyZSBlc2NhcGVkIHdpdGggYW5vdGhlciBkb3VibGUgcXVvdGUuPC9wPgogICAgICoKICAgICAqIDxwPklmIHRoZSB2YWx1ZSBkb2VzIG5vdCBjb250YWluIGEgY29tbWEsIG5ld2xpbmUgb3IgZG91YmxlIHF1b3RlLCB0aGVuIHRoZQogICAgICogICAgU3RyaW5nIHZhbHVlIGlzIHJldHVybmVkIHVuY2hhbmdlZC48L3A+CiAgICAgKgogICAgICogc2VlIDxhIGhyZWY9Imh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tbWEtc2VwYXJhdGVkX3ZhbHVlcyI+V2lraXBlZGlhPC9hPiBhbmQKICAgICAqIDxhIGhyZWY9Imh0dHA6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzQxODAiPlJGQyA0MTgwPC9hPi4KICAgICAqCiAgICAgKiBAcGFyYW0gaW5wdXQgdGhlIGlucHV0IENTViBjb2x1bW4gU3RyaW5nLCBtYXkgYmUgbnVsbAogICAgICogQHJldHVybiB0aGUgaW5wdXQgU3RyaW5nLCBlbmNsb3NlZCBpbiBkb3VibGUgcXVvdGVzIGlmIHRoZSB2YWx1ZSBjb250YWlucyBhIGNvbW1hLAogICAgICogbmV3bGluZSBvciBkb3VibGUgcXVvdGUsIHtAY29kZSBudWxsfSBpZiBudWxsIHN0cmluZyBpbnB1dAogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBlc2NhcGVDc3YoZmluYWwgU3RyaW5nIGlucHV0KSB7CiAgICAgICAgcmV0dXJuIEVTQ0FQRV9DU1YudHJhbnNsYXRlKGlucHV0KTsKICAgIH0KCiAgICAvKioKICAgICAqIDxwPlJldHVybnMgYSB7QGNvZGUgU3RyaW5nfSB2YWx1ZSBmb3IgYW4gdW5lc2NhcGVkIENTViBjb2x1bW4uIDwvcD4KICAgICAqCiAgICAgKiA8cD5JZiB0aGUgdmFsdWUgaXMgZW5jbG9zZWQgaW4gZG91YmxlIHF1b3RlcywgYW5kIGNvbnRhaW5zIGEgY29tbWEsIG5ld2xpbmUgCiAgICAgKiAgICBvciBkb3VibGUgcXVvdGUsIHRoZW4gcXVvdGVzIGFyZSByZW1vdmVkLiAKICAgICAqIDwvcD4KICAgICAqCiAgICAgKiA8cD5BbnkgZG91YmxlIHF1b3RlIGVzY2FwZWQgY2hhcmFjdGVycyAoYSBwYWlyIG9mIGRvdWJsZSBxdW90ZXMpIGFyZSB1bmVzY2FwZWQgCiAgICAgKiAgICB0byBqdXN0IG9uZSBkb3VibGUgcXVvdGUuIDwvcD4KICAgICAqCiAgICAgKiA8cD5JZiB0aGUgdmFsdWUgaXMgbm90IGVuY2xvc2VkIGluIGRvdWJsZSBxdW90ZXMsIG9yIGlzIGFuZCBkb2VzIG5vdCBjb250YWluIGEgCiAgICAgKiAgICBjb21tYSwgbmV3bGluZSBvciBkb3VibGUgcXVvdGUsIHRoZW4gdGhlIFN0cmluZyB2YWx1ZSBpcyByZXR1cm5lZCB1bmNoYW5nZWQuPC9wPgogICAgICoKICAgICAqIHNlZSA8YSBocmVmPSJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbW1hLXNlcGFyYXRlZF92YWx1ZXMiPldpa2lwZWRpYTwvYT4gYW5kCiAgICAgKiA8YSBocmVmPSJodHRwOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM0MTgwIj5SRkMgNDE4MDwvYT4uCiAgICAgKgogICAgICogQHBhcmFtIGlucHV0IHRoZSBpbnB1dCBDU1YgY29sdW1uIFN0cmluZywgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gdGhlIGlucHV0IFN0cmluZywgd2l0aCBlbmNsb3NpbmcgZG91YmxlIHF1b3RlcyByZW1vdmVkIGFuZCBlbWJlZGRlZCBkb3VibGUgCiAgICAgKiBxdW90ZXMgdW5lc2NhcGVkLCB7QGNvZGUgbnVsbH0gaWYgbnVsbCBzdHJpbmcgaW5wdXQKICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBTdHJpbmcgdW5lc2NhcGVDc3YoZmluYWwgU3RyaW5nIGlucHV0KSB7CiAgICAgICAgcmV0dXJuIFVORVNDQVBFX0NTVi50cmFuc2xhdGUoaW5wdXQpOwogICAgfQoKICAgIC8qKgogICAgICogPHA+RXNjYXBlcyB0aGUgY2hhcmFjdGVycyBpbiBhIHtAY29kZSBTdHJpbmd9IHVzaW5nIFhTSSBydWxlcy48L3A+CiAgICAgKgogICAgICogPHA+PGI+QmV3YXJlITwvYj4gSW4gbW9zdCBjYXNlcyB5b3UgZG9uJ3Qgd2FudCB0byBlc2NhcGUgc2hlbGwgY29tbWFuZHMgYnV0IHVzZSBtdWx0aS1hcmd1bWVudAogICAgICogbWV0aG9kcyBwcm92aWRlZCBieSB7QGxpbmsgamF2YS5sYW5nLlByb2Nlc3NCdWlsZGVyfSBvciB7QGxpbmsgamF2YS5sYW5nLlJ1bnRpbWUjZXhlYyhTdHJpbmdbXSl9CiAgICAgKiBpbnN0ZWFkLjwvcD4KICAgICAqCiAgICAgKiA8cD5FeGFtcGxlOjwvcD4KICAgICAqIDxwcmU+CiAgICAgKiBpbnB1dCBzdHJpbmc6IEhlIGRpZG4ndCBzYXksICJTdG9wISIKICAgICAqIG91dHB1dCBzdHJpbmc6IEhlXCBkaWRuXCd0XCBzYXksXCBcIlN0b3AhXCIKICAgICAqIDwvcHJlPgogICAgICoKICAgICAqIEBzZWUgPGEgaHJlZj0iaHR0cDovL3B1YnMub3Blbmdyb3VwLm9yZy9vbmxpbmVwdWJzLzc5MDg3OTkveGN1L2NoYXAyLmh0bWwiPlNoZWxsIENvbW1hbmQgTGFuZ3VhZ2U8L2E+CiAgICAgKiBAcGFyYW0gaW5wdXQgIFN0cmluZyB0byBlc2NhcGUgdmFsdWVzIGluLCBtYXkgYmUgbnVsbAogICAgICogQHJldHVybiBTdHJpbmcgd2l0aCBlc2NhcGVkIHZhbHVlcywge0Bjb2RlIG51bGx9IGlmIG51bGwgc3RyaW5nIGlucHV0CiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgZmluYWwgU3RyaW5nIGVzY2FwZVhTSShmaW5hbCBTdHJpbmcgaW5wdXQpIHsKICAgICAgICByZXR1cm4gRVNDQVBFX1hTSS50cmFuc2xhdGUoaW5wdXQpOwogICAgfQoKICAgIC8qKgogICAgICogPHA+VW5lc2NhcGVzIHRoZSBjaGFyYWN0ZXJzIGluIGEge0Bjb2RlIFN0cmluZ30gdXNpbmcgWFNJIHJ1bGVzLjwvcD4KICAgICAqCiAgICAgKiBAc2VlIFN0cmluZ0VzY2FwZVV0aWxzI2VzY2FwZVhTSShTdHJpbmcpCiAgICAgKiBAcGFyYW0gaW5wdXQgIHRoZSB7QGNvZGUgU3RyaW5nfSB0byB1bmVzY2FwZSwgbWF5IGJlIG51bGwKICAgICAqIEByZXR1cm4gYSBuZXcgdW5lc2NhcGVkIHtAY29kZSBTdHJpbmd9LCB7QGNvZGUgbnVsbH0gaWYgbnVsbCBzdHJpbmcgaW5wdXQKICAgICAqLwogICAgcHVibGljIHN0YXRpYyBmaW5hbCBTdHJpbmcgdW5lc2NhcGVYU0koZmluYWwgU3RyaW5nIGlucHV0KSB7CiAgICAgICAgcmV0dXJuIFVORVNDQVBFX1hTSS50cmFuc2xhdGUoaW5wdXQpOwogICAgfQoKfQ==