{ "name": "ASAStakingContract", "structs": { "UserStakeInfo": [ { "name": "stakedAmount", "type": "uint64" }, { "name": "firstStakeTime", "type": "uint64" }, { "name": "lastStakeTime", "type": "uint64" }, { "name": "totalRewardsEarned", "type": "uint64" }, { "name": "rewardDebt", "type": "uint64" }, { "name": "pendingRewards", "type": "uint64" } ] }, "methods": [ { "name": "getUserStakeInfo", "args": [ { "type": "account", "name": "userAddress" } ], "returns": { "type": "(uint64,uint64,uint64,uint64,uint64,uint64)", "struct": "UserStakeInfo" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Helper function to read user stake info from box storage", "events": [], "recommendations": {} }, { "name": "storeUserStakeInfo", "args": [ { "type": "account", "name": "userAddress" }, { "type": "(uint64,uint64,uint64,uint64,uint64,uint64)", "struct": "UserStakeInfo", "name": "stakeInfo" } ], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Helper function to store user stake info in box storage", "events": [], "recommendations": {} }, { "name": "initialize", "args": [ { "type": "asset", "name": "asset" }, { "type": "account", "name": "adminAddress" }, { "type": "uint64", "name": "minimumStake" }, { "type": "uint64", "name": "weeklyRewards" }, { "type": "uint64", "name": "rewardPeriod" } ], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Initialize the contract with the ASA token ID and other parameters", "events": [], "recommendations": {} }, { "name": "optInToAsset", "args": [], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Opt the contract into the ASA", "events": [], "recommendations": {} }, { "name": "stake", "args": [], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Stake tokens\nRequires a companion ASA transfer transaction\nAutomatically claims pending rewards", "events": [], "recommendations": {} }, { "name": "withdraw", "args": [ { "type": "uint64", "name": "amount" } ], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Withdraw staked tokens\nAutomatically claims pending rewards", "events": [], "recommendations": {} }, { "name": "addRewards", "args": [], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Add rewards to the reward pool\nOnly the admin can call this\nRequires a companion ASA transfer transaction with the rewards", "events": [], "recommendations": {} }, { "name": "getCurrentAPY", "args": [], "returns": { "type": "uint64" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": true, "desc": "Calculate current APY based on total staked amount", "events": [], "recommendations": {} }, { "name": "getPendingRewards", "args": [ { "type": "account", "name": "userAddress" } ], "returns": { "type": "uint64" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": true, "desc": "Get pending rewards for a specific user", "events": [], "recommendations": {} }, { "name": "triggerRewardDistribution", "args": [], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Trigger reward distribution manually (admin only)\nUpdates accumulated rewards per share if period has passed\nand compounds rewards for all stakers", "events": [], "recommendations": {} }, { "name": "updateAdmin", "args": [ { "type": "account", "name": "newAdminAddress" } ], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Update the admin address\nOnly the current admin can call this", "events": [], "recommendations": {} }, { "name": "getUserStats", "args": [ { "type": "account", "name": "userAddress" } ], "returns": { "type": "uint64[]" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": true, "desc": "Get current staking statistics for a user", "events": [], "recommendations": {} }, { "name": "getContractStats", "args": [], "returns": { "type": "uint64[]" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": true, "desc": "Get contract global statistics", "events": [], "recommendations": {} }, { "name": "emergencyWithdrawRewards", "args": [ { "type": "uint64", "name": "amount" } ], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Emergency withdraw rewards from pool (admin only)", "events": [], "recommendations": {} }, { "name": "deleteUserBox", "args": [ { "type": "account", "name": "userAddress" } ], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Delete a user's box (for cleanup)\nCan only be called by the box owner or admin", "events": [], "recommendations": {} }, { "name": "updateWeeklyRewards", "args": [ { "type": "uint64", "name": "newWeeklyRewards" } ], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Update weekly rewards amount (admin only)", "events": [], "recommendations": {} }, { "name": "updateRewardPeriod", "args": [ { "type": "uint64", "name": "newRewardPeriod" } ], "returns": { "type": "void" }, "actions": { "create": [], "call": [ "NoOp" ] }, "readonly": false, "desc": "Update reward period (admin only)", "events": [], "recommendations": {} } ], "arcs": [ 22, 28 ], "desc": "ASA Staking Contract for Algorand with Fixed Weekly Reward Pool\n\nThis contract allows users to:\n- Stake an ASA token\n- Earn proportional rewards from a fixed weekly pool of 100,000 tokens\n- Add to their stake at any time\n- Withdraw part or all of their stake at any time\n- Claim rewards at any time\n- Dynamic APY that adjusts based on total staked amount\n\nThis implementation uses box storage to store user staking information\nand an accumulator pattern for gas-efficient reward distribution", "networks": {}, "state": { "schema": { "global": { "ints": 8, "bytes": 8 }, "local": { "ints": 0, "bytes": 0 } }, "keys": { "global": { "asset": { "keyType": "AVMString", "valueType": "AVMUint64", "key": "YXNzZXQ=" }, "adminAddress": { "keyType": "AVMString", "valueType": "address", "key": "YWRtaW5BZGRyZXNz" }, "totalStaked": { "keyType": "AVMString", "valueType": "AVMUint64", "key": "dG90YWxTdGFrZWQ=" }, "lastRewardTime": { "keyType": "AVMString", "valueType": "AVMUint64", "key": "bGFzdFJld2FyZFRpbWU=" }, "minimumStake": { "keyType": "AVMString", "valueType": "AVMUint64", "key": "bWluaW11bVN0YWtl" }, "rewardPool": { "keyType": "AVMString", "valueType": "AVMUint64", "key": "cmV3YXJkUG9vbA==" }, "accumulatedRewardsPerShare": { "keyType": "AVMString", "valueType": "AVMUint64", "key": "YWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmU=" }, "weeklyRewards": { "keyType": "AVMString", "valueType": "AVMUint64", "key": "d2Vla2x5UmV3YXJkcw==" }, "rewardPeriod": { "keyType": "AVMString", "valueType": "AVMUint64", "key": "cmV3YXJkUGVyaW9k" } }, "local": {}, "box": {} }, "maps": { "global": {}, "local": {}, "box": { "stakers": { "keyType": "address", "valueType": "UserStakeInfo", "prefix": "c3Rha2Vycw==" } } } }, "bareActions": { "create": [ "NoOp" ], "call": [] }, "sourceInfo": { "approval": { "sourceInfo": [ { "pc": [ 894 ], "errorMessage": "Already initialized" }, { "pc": [ 1026, 1261 ], "errorMessage": "Asset transfer must be to contract" }, { "pc": [ 657 ], "errorMessage": "Box must have value" }, { "pc": [ 1003 ], "errorMessage": "Contract not initialized" }, { "pc": [ 1009, 1240 ], "errorMessage": "Expected 2 txns in group" }, { "pc": [ 1038, 1273 ], "errorMessage": "Incorrect asset ID" }, { "pc": [ 1062 ], "errorMessage": "Initial stake below minimum" }, { "pc": [ 1527 ], "errorMessage": "Insufficient reward pool" }, { "pc": [ 1266 ], "errorMessage": "Must provide non-zero rewards" }, { "pc": [ 1033 ], "errorMessage": "Must stake non-zero amount" }, { "pc": [ 1134 ], "errorMessage": "No stake found" }, { "pc": [ 320, 336, 352, 370, 386, 403, 426, 444, 456, 480, 498, 510, 526, 538, 550, 586, 608 ], "errorMessage": "OnCompletion is not NoOp" }, { "pc": [ 1234 ], "errorMessage": "Only admin can add rewards" }, { "pc": [ 1519 ], "errorMessage": "Only admin can emergency withdraw" }, { "pc": [ 1332 ], "errorMessage": "Only admin can trigger distribution" }, { "pc": [ 1347 ], "errorMessage": "Only admin can update admin" }, { "pc": [ 1649 ], "errorMessage": "Only admin can update reward period" }, { "pc": [ 1629 ], "errorMessage": "Only admin can update weekly rewards" }, { "pc": [ 1586 ], "errorMessage": "Only box owner or admin can delete box" }, { "pc": [ 900 ], "errorMessage": "Only creator can initialize" }, { "pc": [ 964 ], "errorMessage": "Only creator or admin can opt in" }, { "pc": [ 1161 ], "errorMessage": "Remaining stake would be below minimum" }, { "pc": [ 1019, 1254 ], "errorMessage": "Transaction 0 must be asset transfer" }, { "pc": [ 1595 ], "errorMessage": "User still has active stake" }, { "pc": [ 1140 ], "errorMessage": "Withdrawal amount exceeds stake" }, { "pc": [ 1143 ], "errorMessage": "Withdrawal amount must be positive" }, { "pc": [ 636 ], "errorMessage": "can only call when creating" }, { "pc": [ 323, 339, 355, 373, 389, 406, 429, 447, 459, 483, 501, 513, 529, 541, 553, 589, 611 ], "errorMessage": "can only call when not creating" }, { "pc": [ 742, 753, 762, 784, 791, 800, 820, 853, 892, 946, 968, 998, 1002, 1043, 1099, 1114, 1159, 1180, 1197, 1207, 1230, 1244, 1277, 1293, 1304, 1328, 1343, 1437, 1441, 1446, 1451, 1456, 1460, 1465, 1513, 1523, 1531, 1541, 1568, 1625, 1645 ], "errorMessage": "check GlobalState exists" }, { "pc": [ 1016, 1251 ], "errorMessage": "transaction type is axfer" } ], "pcOffsetMethod": "none" }, "clear": { "sourceInfo": [], "pcOffsetMethod": "none" } }, "source": { "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCiNwcmFnbWEgdHlwZXRyYWNrIGZhbHNlCgovLyBAYWxnb3JhbmRmb3VuZGF0aW9uL2FsZ29yYW5kLXR5cGVzY3JpcHQvYXJjNC9pbmRleC5kLnRzOjpDb250cmFjdC5hcHByb3ZhbFByb2dyYW0oKSAtPiB1aW50NjQ6Cm1haW46CiAgICBpbnRjYmxvY2sgMCAxIDQgOAogICAgYnl0ZWNibG9jayAiYWRtaW5BZGRyZXNzIiAiYXNzZXQiICJ0b3RhbFN0YWtlZCIgInJld2FyZFBvb2wiICJhY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZSIgImxhc3RSZXdhcmRUaW1lIiAibWluaW11bVN0YWtlIiAid2Vla2x5UmV3YXJkcyIgInJld2FyZFBlcmlvZCIgMHgxNTFmN2M3NSAic3Rha2VycyIKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBibnogbWFpbl9hZnRlcl9pZl9lbHNlQDIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTQKICAgIC8vIHB1YmxpYyBhc3NldCA9IEdsb2JhbFN0YXRlPEFzc2V0Pih7IGluaXRpYWxWYWx1ZTogQXNzZXQoKSB9KQogICAgYnl0ZWNfMSAvLyAiYXNzZXQiCiAgICBpbnRjXzAgLy8gMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTUKICAgIC8vIHB1YmxpYyBhZG1pbkFkZHJlc3MgPSBHbG9iYWxTdGF0ZTxBY2NvdW50Pih7IGluaXRpYWxWYWx1ZTogQWNjb3VudCgpfSkKICAgIGJ5dGVjXzAgLy8gImFkbWluQWRkcmVzcyIKICAgIGdsb2JhbCBaZXJvQWRkcmVzcwogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYKICAgIC8vIHB1YmxpYyB0b3RhbFN0YWtlZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGJ5dGVjXzIgLy8gInRvdGFsU3Rha2VkIgogICAgaW50Y18wIC8vIDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU3CiAgICAvLyBwdWJsaWMgbGFzdFJld2FyZFRpbWUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlYyA1IC8vICJsYXN0UmV3YXJkVGltZSIKICAgIGludGNfMCAvLyAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1OAogICAgLy8gcHVibGljIG1pbmltdW1TdGFrZSA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGJ5dGVjIDYgLy8gIm1pbmltdW1TdGFrZSIKICAgIGludGNfMCAvLyAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1OQogICAgLy8gcHVibGljIHJld2FyZFBvb2wgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlY18zIC8vICJyZXdhcmRQb29sIgogICAgaW50Y18wIC8vIDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjYwCiAgICAvLyBwdWJsaWMgYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlYyA0IC8vICJhY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZSIKICAgIGludGNfMCAvLyAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2MwogICAgLy8gcHVibGljIHdlZWtseVJld2FyZHMgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlYyA3IC8vICJ3ZWVrbHlSZXdhcmRzIgogICAgaW50Y18wIC8vIDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjY0CiAgICAvLyBwdWJsaWMgcmV3YXJkUGVyaW9kID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgYnl0ZWMgOCAvLyAicmV3YXJkUGVyaW9kIgogICAgaW50Y18wIC8vIDAKICAgIGFwcF9nbG9iYWxfcHV0CgptYWluX2FmdGVyX2lmX2Vsc2VAMjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTItNTMKICAgIC8vIEBjb250cmFjdCh7IHN0YXRlVG90YWxzOiB7IGdsb2JhbEJ5dGVzOiA4IH0gfSkKICAgIC8vIGV4cG9ydCBjbGFzcyBBU0FTdGFraW5nQ29udHJhY3QgZXh0ZW5kcyBDb250cmFjdCB7CiAgICB0eG4gTnVtQXBwQXJncwogICAgYnogbWFpbl9iYXJlX3JvdXRpbmdAMjQKICAgIHB1c2hieXRlc3MgMHg2NWUxNjk0ZiAweDNjM2JlNTVlIDB4NjY3YzVkMzAgMHg5ZmZkM2U1MyAweDA4OTBiZDU4IDB4MjFmMWRkZmYgMHhiM2I3MDE0NiAweGJmOGI3NjZkIDB4MTgzODM4ZTkgMHgyMWIxYjAyMiAweDgyYWIxZWM0IDB4MTU3NjZiMDkgMHhiZmUzMTU2NCAweGNlOTYzYjFkIDB4ZGM5YTJhMDUgMHgxZTJiNTJhYiAweDFiODc0YWQ2IC8vIG1ldGhvZCAiZ2V0VXNlclN0YWtlSW5mbyhhY2NvdW50KSh1aW50NjQsdWludDY0LHVpbnQ2NCx1aW50NjQsdWludDY0LHVpbnQ2NCkiLCBtZXRob2QgInN0b3JlVXNlclN0YWtlSW5mbyhhY2NvdW50LCh1aW50NjQsdWludDY0LHVpbnQ2NCx1aW50NjQsdWludDY0LHVpbnQ2NCkpdm9pZCIsIG1ldGhvZCAiaW5pdGlhbGl6ZShhc3NldCxhY2NvdW50LHVpbnQ2NCx1aW50NjQsdWludDY0KXZvaWQiLCBtZXRob2QgIm9wdEluVG9Bc3NldCgpdm9pZCIsIG1ldGhvZCAic3Rha2UoKXZvaWQiLCBtZXRob2QgIndpdGhkcmF3KHVpbnQ2NCl2b2lkIiwgbWV0aG9kICJhZGRSZXdhcmRzKCl2b2lkIiwgbWV0aG9kICJnZXRDdXJyZW50QVBZKCl1aW50NjQiLCBtZXRob2QgImdldFBlbmRpbmdSZXdhcmRzKGFjY291bnQpdWludDY0IiwgbWV0aG9kICJ0cmlnZ2VyUmV3YXJkRGlzdHJpYnV0aW9uKCl2b2lkIiwgbWV0aG9kICJ1cGRhdGVBZG1pbihhY2NvdW50KXZvaWQiLCBtZXRob2QgImdldFVzZXJTdGF0cyhhY2NvdW50KXVpbnQ2NFtdIiwgbWV0aG9kICJnZXRDb250cmFjdFN0YXRzKCl1aW50NjRbXSIsIG1ldGhvZCAiZW1lcmdlbmN5V2l0aGRyYXdSZXdhcmRzKHVpbnQ2NCl2b2lkIiwgbWV0aG9kICJkZWxldGVVc2VyQm94KGFjY291bnQpdm9pZCIsIG1ldGhvZCAidXBkYXRlV2Vla2x5UmV3YXJkcyh1aW50NjQpdm9pZCIsIG1ldGhvZCAidXBkYXRlUmV3YXJkUGVyaW9kKHVpbnQ2NCl2b2lkIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggbWFpbl9nZXRVc2VyU3Rha2VJbmZvX3JvdXRlQDUgbWFpbl9zdG9yZVVzZXJTdGFrZUluZm9fcm91dGVANiBtYWluX2luaXRpYWxpemVfcm91dGVANyBtYWluX29wdEluVG9Bc3NldF9yb3V0ZUA4IG1haW5fc3Rha2Vfcm91dGVAOSBtYWluX3dpdGhkcmF3X3JvdXRlQDEwIG1haW5fYWRkUmV3YXJkc19yb3V0ZUAxMSBtYWluX2dldEN1cnJlbnRBUFlfcm91dGVAMTIgbWFpbl9nZXRQZW5kaW5nUmV3YXJkc19yb3V0ZUAxMyBtYWluX3RyaWdnZXJSZXdhcmREaXN0cmlidXRpb25fcm91dGVAMTQgbWFpbl91cGRhdGVBZG1pbl9yb3V0ZUAxNSBtYWluX2dldFVzZXJTdGF0c19yb3V0ZUAxNiBtYWluX2dldENvbnRyYWN0U3RhdHNfcm91dGVAMTcgbWFpbl9lbWVyZ2VuY3lXaXRoZHJhd1Jld2FyZHNfcm91dGVAMTggbWFpbl9kZWxldGVVc2VyQm94X3JvdXRlQDE5IG1haW5fdXBkYXRlV2Vla2x5UmV3YXJkc19yb3V0ZUAyMCBtYWluX3VwZGF0ZVJld2FyZFBlcmlvZF9yb3V0ZUAyMQoKbWFpbl9hZnRlcl9pZl9lbHNlQDI4OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1Mi01MwogICAgLy8gQGNvbnRyYWN0KHsgc3RhdGVUb3RhbHM6IHsgZ2xvYmFsQnl0ZXM6IDggfSB9KQogICAgLy8gZXhwb3J0IGNsYXNzIEFTQVN0YWtpbmdDb250cmFjdCBleHRlbmRzIENvbnRyYWN0IHsKICAgIGludGNfMCAvLyAwCiAgICByZXR1cm4KCm1haW5fdXBkYXRlUmV3YXJkUGVyaW9kX3JvdXRlQDIxOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1MTYKICAgIC8vIEBhYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUyLTUzCiAgICAvLyBAY29udHJhY3QoeyBzdGF0ZVRvdGFsczogeyBnbG9iYWxCeXRlczogOCB9IH0pCiAgICAvLyBleHBvcnQgY2xhc3MgQVNBU3Rha2luZ0NvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1MTYKICAgIC8vIEBhYmltZXRob2QoKQogICAgY2FsbHN1YiB1cGRhdGVSZXdhcmRQZXJpb2QKICAgIGludGNfMSAvLyAxCiAgICByZXR1cm4KCm1haW5fdXBkYXRlV2Vla2x5UmV3YXJkc19yb3V0ZUAyMDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTAwCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1Mi01MwogICAgLy8gQGNvbnRyYWN0KHsgc3RhdGVUb3RhbHM6IHsgZ2xvYmFsQnl0ZXM6IDggfSB9KQogICAgLy8gZXhwb3J0IGNsYXNzIEFTQVN0YWtpbmdDb250cmFjdCBleHRlbmRzIENvbnRyYWN0IHsKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGJ0b2kKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTAwCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIGNhbGxzdWIgdXBkYXRlV2Vla2x5UmV3YXJkcwogICAgaW50Y18xIC8vIDEKICAgIHJldHVybgoKbWFpbl9kZWxldGVVc2VyQm94X3JvdXRlQDE5OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0NzgKICAgIC8vIEBhYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUyLTUzCiAgICAvLyBAY29udHJhY3QoeyBzdGF0ZVRvdGFsczogeyBnbG9iYWxCeXRlczogOCB9IH0pCiAgICAvLyBleHBvcnQgY2xhc3MgQVNBU3Rha2luZ0NvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQWNjb3VudHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDc4CiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIGNhbGxzdWIgZGVsZXRlVXNlckJveAogICAgaW50Y18xIC8vIDEKICAgIHJldHVybgoKbWFpbl9lbWVyZ2VuY3lXaXRoZHJhd1Jld2FyZHNfcm91dGVAMTg6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ1MAogICAgLy8gQGFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTItNTMKICAgIC8vIEBjb250cmFjdCh7IHN0YXRlVG90YWxzOiB7IGdsb2JhbEJ5dGVzOiA4IH0gfSkKICAgIC8vIGV4cG9ydCBjbGFzcyBBU0FTdGFraW5nQ29udHJhY3QgZXh0ZW5kcyBDb250cmFjdCB7CiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBidG9pCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ1MAogICAgLy8gQGFiaW1ldGhvZCgpCiAgICBjYWxsc3ViIGVtZXJnZW5jeVdpdGhkcmF3UmV3YXJkcwogICAgaW50Y18xIC8vIDEKICAgIHJldHVybgoKbWFpbl9nZXRDb250cmFjdFN0YXRzX3JvdXRlQDE3OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MjkKICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGdldENvbnRyYWN0U3RhdHMKICAgIGJ5dGVjIDkgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMSAvLyAxCiAgICByZXR1cm4KCm1haW5fZ2V0VXNlclN0YXRzX3JvdXRlQDE2OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MDgKICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUyLTUzCiAgICAvLyBAY29udHJhY3QoeyBzdGF0ZVRvdGFsczogeyBnbG9iYWxCeXRlczogOCB9IH0pCiAgICAvLyBleHBvcnQgY2xhc3MgQVNBU3Rha2luZ0NvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQWNjb3VudHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDA4CiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIGNhbGxzdWIgZ2V0VXNlclN0YXRzCiAgICBieXRlYyA5IC8vIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnRjXzEgLy8gMQogICAgcmV0dXJuCgptYWluX3VwZGF0ZUFkbWluX3JvdXRlQDE1OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozOTUKICAgIC8vIEBhYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUyLTUzCiAgICAvLyBAY29udHJhY3QoeyBzdGF0ZVRvdGFsczogeyBnbG9iYWxCeXRlczogOCB9IH0pCiAgICAvLyBleHBvcnQgY2xhc3MgQVNBU3Rha2luZ0NvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQWNjb3VudHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mzk1CiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIGNhbGxzdWIgdXBkYXRlQWRtaW4KICAgIGludGNfMSAvLyAxCiAgICByZXR1cm4KCm1haW5fdHJpZ2dlclJld2FyZERpc3RyaWJ1dGlvbl9yb3V0ZUAxNDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mzc1CiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiB0cmlnZ2VyUmV3YXJkRGlzdHJpYnV0aW9uCiAgICBpbnRjXzEgLy8gMQogICAgcmV0dXJuCgptYWluX2dldFBlbmRpbmdSZXdhcmRzX3JvdXRlQDEzOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozNjUKICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUyLTUzCiAgICAvLyBAY29udHJhY3QoeyBzdGF0ZVRvdGFsczogeyBnbG9iYWxCeXRlczogOCB9IH0pCiAgICAvLyBleHBvcnQgY2xhc3MgQVNBU3Rha2luZ0NvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQWNjb3VudHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzY1CiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIGNhbGxzdWIgZ2V0UGVuZGluZ1Jld2FyZHMKICAgIGl0b2IKICAgIGJ5dGVjIDkgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMSAvLyAxCiAgICByZXR1cm4KCm1haW5fZ2V0Q3VycmVudEFQWV9yb3V0ZUAxMjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzQ1CiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBnZXRDdXJyZW50QVBZCiAgICBpdG9iCiAgICBieXRlYyA5IC8vIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnRjXzEgLy8gMQogICAgcmV0dXJuCgptYWluX2FkZFJld2FyZHNfcm91dGVAMTE6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjMyMQogICAgLy8gQGFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYWRkUmV3YXJkcwogICAgaW50Y18xIC8vIDEKICAgIHJldHVybgoKbWFpbl93aXRoZHJhd19yb3V0ZUAxMDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mjc0CiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1Mi01MwogICAgLy8gQGNvbnRyYWN0KHsgc3RhdGVUb3RhbHM6IHsgZ2xvYmFsQnl0ZXM6IDggfSB9KQogICAgLy8gZXhwb3J0IGNsYXNzIEFTQVN0YWtpbmdDb250cmFjdCBleHRlbmRzIENvbnRyYWN0IHsKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGJ0b2kKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mjc0CiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIGNhbGxzdWIgd2l0aGRyYXcKICAgIGludGNfMSAvLyAxCiAgICByZXR1cm4KCm1haW5fc3Rha2Vfcm91dGVAOToKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjI1CiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBzdGFrZQogICAgaW50Y18xIC8vIDEKICAgIHJldHVybgoKbWFpbl9vcHRJblRvQXNzZXRfcm91dGVAODoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjAzCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBvcHRJblRvQXNzZXQKICAgIGludGNfMSAvLyAxCiAgICByZXR1cm4KCm1haW5faW5pdGlhbGl6ZV9yb3V0ZUA3OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxNzIKICAgIC8vIEBhYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUyLTUzCiAgICAvLyBAY29udHJhY3QoeyBzdGF0ZVRvdGFsczogeyBnbG9iYWxCeXRlczogOCB9IH0pCiAgICAvLyBleHBvcnQgY2xhc3MgQVNBU3Rha2luZ0NvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQXNzZXRzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBidG9pCiAgICB0eG5hcyBBY2NvdW50cwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgYnRvaQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgYnRvaQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNQogICAgYnRvaQogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxNzIKICAgIC8vIEBhYmltZXRob2QoKQogICAgY2FsbHN1YiBpbml0aWFsaXplCiAgICBpbnRjXzEgLy8gMQogICAgcmV0dXJuCgptYWluX3N0b3JlVXNlclN0YWtlSW5mb19yb3V0ZUA2OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo5MQogICAgLy8gcHVibGljIHN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCwgc3Rha2VJbmZvOiBVc2VyU3Rha2VJbmZvKTogdm9pZCB7CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTItNTMKICAgIC8vIEBjb250cmFjdCh7IHN0YXRlVG90YWxzOiB7IGdsb2JhbEJ5dGVzOiA4IH0gfSkKICAgIC8vIGV4cG9ydCBjbGFzcyBBU0FTdGFraW5nQ29udHJhY3QgZXh0ZW5kcyBDb250cmFjdCB7CiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBidG9pCiAgICB0eG5hcyBBY2NvdW50cwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo5MQogICAgLy8gcHVibGljIHN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCwgc3Rha2VJbmZvOiBVc2VyU3Rha2VJbmZvKTogdm9pZCB7CiAgICBjYWxsc3ViIHN0b3JlVXNlclN0YWtlSW5mbwogICAgcG9wCiAgICBpbnRjXzEgLy8gMQogICAgcmV0dXJuCgptYWluX2dldFVzZXJTdGFrZUluZm9fcm91dGVANToKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NzEKICAgIC8vIHB1YmxpYyBnZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogVXNlclN0YWtlSW5mbyB7CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTItNTMKICAgIC8vIEBjb250cmFjdCh7IHN0YXRlVG90YWxzOiB7IGdsb2JhbEJ5dGVzOiA4IH0gfSkKICAgIC8vIGV4cG9ydCBjbGFzcyBBU0FTdGFraW5nQ29udHJhY3QgZXh0ZW5kcyBDb250cmFjdCB7CiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBidG9pCiAgICB0eG5hcyBBY2NvdW50cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo3MQogICAgLy8gcHVibGljIGdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3M6IEFjY291bnQpOiBVc2VyU3Rha2VJbmZvIHsKICAgIGNhbGxzdWIgZ2V0VXNlclN0YWtlSW5mbwogICAgYnl0ZWMgOSAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18xIC8vIDEKICAgIHJldHVybgoKbWFpbl9iYXJlX3JvdXRpbmdAMjQ6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUyLTUzCiAgICAvLyBAY29udHJhY3QoeyBzdGF0ZVRvdGFsczogeyBnbG9iYWxCeXRlczogOCB9IH0pCiAgICAvLyBleHBvcnQgY2xhc3MgQVNBU3Rha2luZ0NvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IG1haW5fYWZ0ZXJfaWZfZWxzZUAyOAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gY3JlYXRpbmcKICAgIGludGNfMSAvLyAxCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3QuZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgpnZXRVc2VyU3Rha2VJbmZvOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo3MQogICAgLy8gcHVibGljIGdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3M6IEFjY291bnQpOiBVc2VyU3Rha2VJbmZvIHsKICAgIHByb3RvIDEgMQogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2NgogICAgLy8gcHVibGljIHN0YWtlcnMgPSBCb3hNYXA8QWNjb3VudCwgVXNlclN0YWtlSW5mbz4oeyBrZXlQcmVmaXg6ICdzdGFrZXJzJyB9KQogICAgYnl0ZWMgMTAgLy8gInN0YWtlcnMiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjcyCiAgICAvLyBjb25zdCB1c2VyQm94ID0gdGhpcy5zdGFrZXJzKHVzZXJBZGRyZXNzKQogICAgZnJhbWVfZGlnIC0xCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjY2CiAgICAvLyBwdWJsaWMgc3Rha2VycyA9IEJveE1hcDxBY2NvdW50LCBVc2VyU3Rha2VJbmZvPih7IGtleVByZWZpeDogJ3N0YWtlcnMnIH0pCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NzIKICAgIC8vIGNvbnN0IHVzZXJCb3ggPSB0aGlzLnN0YWtlcnModXNlckFkZHJlc3MpCiAgICBkdXAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NzQKICAgIC8vIGlmICh1c2VyQm94LmV4aXN0cykgewogICAgYm94X2xlbgogICAgYnVyeSAxCiAgICBieiBnZXRVc2VyU3Rha2VJbmZvX2Vsc2VfYm9keUAyCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjc1CiAgICAvLyByZXR1cm4gdXNlckJveC52YWx1ZS5jb3B5KCkKICAgIGZyYW1lX2RpZyAwCiAgICBib3hfZ2V0CiAgICBhc3NlcnQgLy8gQm94IG11c3QgaGF2ZSB2YWx1ZQogICAgc3dhcAogICAgcmV0c3ViCgpnZXRVc2VyU3Rha2VJbmZvX2Vsc2VfYm9keUAyOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo3Ny04NAogICAgLy8gcmV0dXJuIG5ldyBVc2VyU3Rha2VJbmZvKHsKICAgIC8vICAgc3Rha2VkQW1vdW50OiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICBmaXJzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgbGFzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgdG90YWxSZXdhcmRzRWFybmVkOiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICByZXdhcmREZWJ0OiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICBwZW5kaW5nUmV3YXJkczogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vIH0pCiAgICBwdXNoYnl0ZXMgMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKICAgIHN3YXAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6OkFTQVN0YWtpbmdDb250cmFjdC5zdG9yZVVzZXJTdGFrZUluZm8odXNlckFkZHJlc3M6IGJ5dGVzLCBzdGFrZUluZm86IGJ5dGVzKSAtPiBieXRlczoKc3RvcmVVc2VyU3Rha2VJbmZvOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo5MQogICAgLy8gcHVibGljIHN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCwgc3Rha2VJbmZvOiBVc2VyU3Rha2VJbmZvKTogdm9pZCB7CiAgICBwcm90byAyIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NjYKICAgIC8vIHB1YmxpYyBzdGFrZXJzID0gQm94TWFwPEFjY291bnQsIFVzZXJTdGFrZUluZm8+KHsga2V5UHJlZml4OiAnc3Rha2VycycgfSkKICAgIGJ5dGVjIDEwIC8vICJzdGFrZXJzIgogICAgZnJhbWVfZGlnIC0yCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6OTIKICAgIC8vIHRoaXMuc3Rha2Vycyh1c2VyQWRkcmVzcykudmFsdWUgPSBzdGFrZUluZm8uY29weSgpCiAgICBmcmFtZV9kaWcgLTEKICAgIGJveF9wdXQKICAgIGZyYW1lX2RpZyAtMQogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo6QVNBU3Rha2luZ0NvbnRyYWN0LnVwZGF0ZVJld2FyZHMoKSAtPiB2b2lkOgp1cGRhdGVSZXdhcmRzOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo5OAogICAgLy8gcHJpdmF0ZSB1cGRhdGVSZXdhcmRzKCk6IHZvaWQgewogICAgcHJvdG8gMCAwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjk5CiAgICAvLyBjb25zdCBjdXJyZW50VGltZSA9IEdsb2JhbC5sYXRlc3RUaW1lc3RhbXAKICAgIGdsb2JhbCBMYXRlc3RUaW1lc3RhbXAKICAgIGR1cAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NwogICAgLy8gcHVibGljIGxhc3RSZXdhcmRUaW1lID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjIDUgLy8gImxhc3RSZXdhcmRUaW1lIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIHN3YXAKICAgIGR1cAogICAgY292ZXIgMgogICAgY292ZXIgMwogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2NAogICAgLy8gcHVibGljIHJld2FyZFBlcmlvZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlYyA4IC8vICJyZXdhcmRQZXJpb2QiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgc3dhcAogICAgZHVwCiAgICBjb3ZlciAyCiAgICBjb3ZlciA0CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjEwNAogICAgLy8gaWYgKGN1cnJlbnRUaW1lID49IGxhc3RSZXdhcmQgKyByZXdhcmRQZXJpb2QgJiYgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSA+IDApIHsKICAgICsKICAgID49CiAgICBieiB1cGRhdGVSZXdhcmRzX2FmdGVyX2lmX2Vsc2VAMwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NgogICAgLy8gcHVibGljIHRvdGFsU3Rha2VkID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzIgLy8gInRvdGFsU3Rha2VkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTA0CiAgICAvLyBpZiAoY3VycmVudFRpbWUgPj0gbGFzdFJld2FyZCArIHJld2FyZFBlcmlvZCAmJiB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID4gMCkgewogICAgYnogdXBkYXRlUmV3YXJkc19hZnRlcl9pZl9lbHNlQDMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTA2CiAgICAvLyBjb25zdCBwZXJpb2RzUGFzc2VkOiB1aW50NjQgPSAoY3VycmVudFRpbWUgLSBsYXN0UmV3YXJkKSAvIHJld2FyZFBlcmlvZAogICAgZnJhbWVfZGlnIDAKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGNvdmVyIDIKICAgIC0KICAgIGZyYW1lX2RpZyAyCiAgICBkdXAKICAgIGNvdmVyIDIKICAgIC8KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NjMKICAgIC8vIHB1YmxpYyB3ZWVrbHlSZXdhcmRzID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjIDcgLy8gIndlZWtseVJld2FyZHMiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxMTAKICAgIC8vIGNvbnN0IHRvdGFsUmV3YXJkczogdWludDY0ID0gcmV3YXJkUGVyUGVyaW9kICogcGVyaW9kc1Bhc3NlZAogICAgZGlnIDEKICAgICoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYKICAgIC8vIHB1YmxpYyB0b3RhbFN0YWtlZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18yIC8vICJ0b3RhbFN0YWtlZCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjExNAogICAgLy8gY29uc3QgcmV3YXJkUGVyU2hhcmU6IHVpbnQ2NCA9IHRvdGFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkCiAgICBkaWcgMQogICAgc3dhcAogICAgLwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2MAogICAgLy8gcHVibGljIGFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjIDQgLy8gImFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTE3CiAgICAvLyB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlID0gdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSArIHJld2FyZFBlclNoYXJlCiAgICArCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjYwCiAgICAvLyBwdWJsaWMgYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlYyA0IC8vICJhY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZSIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTE3CiAgICAvLyB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlID0gdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSArIHJld2FyZFBlclNoYXJlCiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxMjAKICAgIC8vIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBsYXN0UmV3YXJkICsgKHBlcmlvZHNQYXNzZWQgKiByZXdhcmRQZXJpb2QpCiAgICBzd2FwCiAgICB1bmNvdmVyIDIKICAgICoKICAgIHVuY292ZXIgMgogICAgKwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NwogICAgLy8gcHVibGljIGxhc3RSZXdhcmRUaW1lID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgYnl0ZWMgNSAvLyAibGFzdFJld2FyZFRpbWUiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjEyMAogICAgLy8gdGhpcy5sYXN0UmV3YXJkVGltZS52YWx1ZSA9IGxhc3RSZXdhcmQgKyAocGVyaW9kc1Bhc3NlZCAqIHJld2FyZFBlcmlvZCkKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU5CiAgICAvLyBwdWJsaWMgcmV3YXJkUG9vbCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18zIC8vICJyZXdhcmRQb29sIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTIzCiAgICAvLyB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSB0aGlzLnJld2FyZFBvb2wudmFsdWUgLSB0b3RhbFJld2FyZHMKICAgIHN3YXAKICAgIC0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTkKICAgIC8vIHB1YmxpYyByZXdhcmRQb29sID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgYnl0ZWNfMyAvLyAicmV3YXJkUG9vbCIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTIzCiAgICAvLyB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSB0aGlzLnJld2FyZFBvb2wudmFsdWUgLSB0b3RhbFJld2FyZHMKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0Cgp1cGRhdGVSZXdhcmRzX2FmdGVyX2lmX2Vsc2VAMzoKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6OkFTQVN0YWtpbmdDb250cmFjdC5jYWxjdWxhdGVQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzczogYnl0ZXMpIC0+IHVpbnQ2NDoKY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHM6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjEzMAogICAgLy8gcHJpdmF0ZSBjYWxjdWxhdGVQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHVpbnQ2NCB7CiAgICBwcm90byAxIDEKICAgIHB1c2hieXRlcyAiIgogICAgZHVwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjEzMQogICAgLy8gY29uc3Qgc3Rha2VJbmZvID0gdGhpcy5nZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzKQogICAgZnJhbWVfZGlnIC0xCiAgICBjYWxsc3ViIGdldFVzZXJTdGFrZUluZm8KICAgIGR1cAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxMzMKICAgIC8vIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA9PT0gMCkgewogICAgaW50Y18wIC8vIDAKICAgIGV4dHJhY3RfdWludDY0CiAgICBkdXAKICAgIGJueiBjYWxjdWxhdGVQZW5kaW5nUmV3YXJkc19hZnRlcl9pZl9lbHNlQDIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTM0CiAgICAvLyByZXR1cm4gMAogICAgaW50Y18wIC8vIDAKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgpjYWxjdWxhdGVQZW5kaW5nUmV3YXJkc19hZnRlcl9pZl9lbHNlQDI6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjYwCiAgICAvLyBwdWJsaWMgYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWMgNCAvLyAiYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxMzkKICAgIC8vIGNvbnN0IHVzZXJSZXdhcmREZWJ0ID0gc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlCiAgICBmcmFtZV9kaWcgMgogICAgcHVzaGludCAzMiAvLyAzMgogICAgZXh0cmFjdF91aW50NjQKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjE0MgogICAgLy8gY29uc3QgdG90YWxFYXJuZWQ6IHVpbnQ2NCA9IHVzZXJTdGFrZSAqIGFjY1Jld2FyZHNQZXJTaGFyZQogICAgZnJhbWVfZGlnIDMKICAgIHVuY292ZXIgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9idXJ5IDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTQzCiAgICAvLyBjb25zdCBwZW5kaW5nUmV3YXJkczogdWludDY0ID0gdG90YWxFYXJuZWQgPiB1c2VyUmV3YXJkRGVidCA/IHRvdGFsRWFybmVkIC0gdXNlclJld2FyZERlYnQgOiAwCiAgICA8CiAgICBieiBjYWxjdWxhdGVQZW5kaW5nUmV3YXJkc190ZXJuYXJ5X2ZhbHNlQDQKICAgIGZyYW1lX2RpZyAwCiAgICBmcmFtZV9kaWcgMQogICAgLQoKY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHNfdGVybmFyeV9tZXJnZUA1OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxNDUKICAgIC8vIHJldHVybiBwZW5kaW5nUmV3YXJkcwogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzX3Rlcm5hcnlfZmFsc2VANDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTQzCiAgICAvLyBjb25zdCBwZW5kaW5nUmV3YXJkczogdWludDY0ID0gdG90YWxFYXJuZWQgPiB1c2VyUmV3YXJkRGVidCA/IHRvdGFsRWFybmVkIC0gdXNlclJld2FyZERlYnQgOiAwCiAgICBpbnRjXzAgLy8gMAogICAgYiBjYWxjdWxhdGVQZW5kaW5nUmV3YXJkc190ZXJuYXJ5X21lcmdlQDUKCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3QuaW5pdGlhbGl6ZShhc3NldDogdWludDY0LCBhZG1pbkFkZHJlc3M6IGJ5dGVzLCBtaW5pbXVtU3Rha2U6IHVpbnQ2NCwgd2Vla2x5UmV3YXJkczogdWludDY0LCByZXdhcmRQZXJpb2Q6IHVpbnQ2NCkgLT4gdm9pZDoKaW5pdGlhbGl6ZToKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTcyLTE3OQogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgaW5pdGlhbGl6ZSgKICAgIC8vICAgYXNzZXQ6IEFzc2V0LAogICAgLy8gICBhZG1pbkFkZHJlc3M6IEFjY291bnQsCiAgICAvLyAgIG1pbmltdW1TdGFrZTogdWludDY0LAogICAgLy8gICB3ZWVrbHlSZXdhcmRzOiB1aW50NjQsCiAgICAvLyAgIHJld2FyZFBlcmlvZDogdWludDY0LAogICAgLy8gKTogdm9pZCB7CiAgICBwcm90byA1IDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTQKICAgIC8vIHB1YmxpYyBhc3NldCA9IEdsb2JhbFN0YXRlPEFzc2V0Pih7IGluaXRpYWxWYWx1ZTogQXNzZXQoKSB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzEgLy8gImFzc2V0IgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTgxCiAgICAvLyBhc3NlcnQodGhpcy5hc3NldC52YWx1ZSA9PT0gQXNzZXQoKSwgJ0FscmVhZHkgaW5pdGlhbGl6ZWQnKQogICAgIQogICAgYXNzZXJ0IC8vIEFscmVhZHkgaW5pdGlhbGl6ZWQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTg0CiAgICAvLyBhc3NlcnQoVHhuLnNlbmRlciA9PT0gR2xvYmFsLmNyZWF0b3JBZGRyZXNzLCAnT25seSBjcmVhdG9yIGNhbiBpbml0aWFsaXplJykKICAgIHR4biBTZW5kZXIKICAgIGdsb2JhbCBDcmVhdG9yQWRkcmVzcwogICAgPT0KICAgIGFzc2VydCAvLyBPbmx5IGNyZWF0b3IgY2FuIGluaXRpYWxpemUKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTQKICAgIC8vIHB1YmxpYyBhc3NldCA9IEdsb2JhbFN0YXRlPEFzc2V0Pih7IGluaXRpYWxWYWx1ZTogQXNzZXQoKSB9KQogICAgYnl0ZWNfMSAvLyAiYXNzZXQiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjE4NwogICAgLy8gdGhpcy5hc3NldC52YWx1ZSA9IGFzc2V0CiAgICBmcmFtZV9kaWcgLTUKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU1CiAgICAvLyBwdWJsaWMgYWRtaW5BZGRyZXNzID0gR2xvYmFsU3RhdGU8QWNjb3VudD4oeyBpbml0aWFsVmFsdWU6IEFjY291bnQoKX0pCiAgICBieXRlY18wIC8vICJhZG1pbkFkZHJlc3MiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjE4OAogICAgLy8gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUgPSBhZG1pbkFkZHJlc3MKICAgIGZyYW1lX2RpZyAtNAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYKICAgIC8vIHB1YmxpYyB0b3RhbFN0YWtlZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGJ5dGVjXzIgLy8gInRvdGFsU3Rha2VkIgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxODkKICAgIC8vIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSAwCiAgICBpbnRjXzAgLy8gMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTcKICAgIC8vIHB1YmxpYyBsYXN0UmV3YXJkVGltZSA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGJ5dGVjIDUgLy8gImxhc3RSZXdhcmRUaW1lIgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxOTAKICAgIC8vIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICBnbG9iYWwgTGF0ZXN0VGltZXN0YW1wCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1OAogICAgLy8gcHVibGljIG1pbmltdW1TdGFrZSA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGJ5dGVjIDYgLy8gIm1pbmltdW1TdGFrZSIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MTkxCiAgICAvLyB0aGlzLm1pbmltdW1TdGFrZS52YWx1ZSA9IG1pbmltdW1TdGFrZQogICAgZnJhbWVfZGlnIC0zCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1OQogICAgLy8gcHVibGljIHJld2FyZFBvb2wgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlY18zIC8vICJyZXdhcmRQb29sIgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxOTIKICAgIC8vIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IDAKICAgIGludGNfMCAvLyAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2MAogICAgLy8gcHVibGljIGFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgYnl0ZWMgNCAvLyAiYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjE5MwogICAgLy8gdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSA9IDAKICAgIGludGNfMCAvLyAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2MwogICAgLy8gcHVibGljIHdlZWtseVJld2FyZHMgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlYyA3IC8vICJ3ZWVrbHlSZXdhcmRzIgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoxOTYKICAgIC8vIHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZSA9IHdlZWtseVJld2FyZHMKICAgIGZyYW1lX2RpZyAtMgogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NjQKICAgIC8vIHB1YmxpYyByZXdhcmRQZXJpb2QgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlYyA4IC8vICJyZXdhcmRQZXJpb2QiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjE5NwogICAgLy8gdGhpcy5yZXdhcmRQZXJpb2QudmFsdWUgPSByZXdhcmRQZXJpb2QKICAgIGZyYW1lX2RpZyAtMQogICAgYXBwX2dsb2JhbF9wdXQKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6OkFTQVN0YWtpbmdDb250cmFjdC5vcHRJblRvQXNzZXQoKSAtPiB2b2lkOgpvcHRJblRvQXNzZXQ6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIwMy0yMDQKICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIG9wdEluVG9Bc3NldCgpOiB2b2lkIHsKICAgIHByb3RvIDAgMAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NQogICAgLy8gcHVibGljIGFkbWluQWRkcmVzcyA9IEdsb2JhbFN0YXRlPEFjY291bnQ+KHsgaW5pdGlhbFZhbHVlOiBBY2NvdW50KCl9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzAgLy8gImFkbWluQWRkcmVzcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIwNwogICAgLy8gYXNzZXJ0KFR4bi5zZW5kZXIgPT09IEdsb2JhbC5jcmVhdG9yQWRkcmVzcyB8fCBUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGNyZWF0b3Igb3IgYWRtaW4gY2FuIG9wdCBpbicpCiAgICB0eG4gU2VuZGVyCiAgICBnbG9iYWwgQ3JlYXRvckFkZHJlc3MKICAgID09CiAgICBibnogb3B0SW5Ub0Fzc2V0X2Jvb2xfdHJ1ZUAyCiAgICB0eG4gU2VuZGVyCiAgICBmcmFtZV9kaWcgMAogICAgPT0KICAgIGJ6IG9wdEluVG9Bc3NldF9ib29sX2ZhbHNlQDMKCm9wdEluVG9Bc3NldF9ib29sX3RydWVAMjoKICAgIGludGNfMSAvLyAxCgpvcHRJblRvQXNzZXRfYm9vbF9tZXJnZUA0OgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyMDcKICAgIC8vIGFzc2VydChUeG4uc2VuZGVyID09PSBHbG9iYWwuY3JlYXRvckFkZHJlc3MgfHwgVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBjcmVhdG9yIG9yIGFkbWluIGNhbiBvcHQgaW4nKQogICAgYXNzZXJ0IC8vIE9ubHkgY3JlYXRvciBvciBhZG1pbiBjYW4gb3B0IGluCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU0CiAgICAvLyBwdWJsaWMgYXNzZXQgPSBHbG9iYWxTdGF0ZTxBc3NldD4oeyBpbml0aWFsVmFsdWU6IEFzc2V0KCkgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18xIC8vICJhc3NldCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIxMS0yMTcKICAgIC8vIGl0eG4KICAgIC8vICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgIGFzc2V0UmVjZWl2ZXI6IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLAogICAgLy8gICAgIGFzc2V0QW1vdW50OiAwLAogICAgLy8gICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgIH0pCiAgICAvLyAgIC5zdWJtaXQoKQogICAgaXR4bl9iZWdpbgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyMTMKICAgIC8vIGFzc2V0UmVjZWl2ZXI6IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLAogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIHN3YXAKICAgIGl0eG5fZmllbGQgWGZlckFzc2V0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIxNAogICAgLy8gYXNzZXRBbW91bnQ6IDAsCiAgICBpbnRjXzAgLy8gMAogICAgaXR4bl9maWVsZCBBc3NldEFtb3VudAogICAgaXR4bl9maWVsZCBBc3NldFJlY2VpdmVyCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIxMS0yMTYKICAgIC8vIGl0eG4KICAgIC8vICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgIGFzc2V0UmVjZWl2ZXI6IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLAogICAgLy8gICAgIGFzc2V0QW1vdW50OiAwLAogICAgLy8gICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgIH0pCiAgICBpbnRjXzIgLy8gNAogICAgaXR4bl9maWVsZCBUeXBlRW51bQogICAgaW50Y18wIC8vIDAKICAgIGl0eG5fZmllbGQgRmVlCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIxMS0yMTcKICAgIC8vIGl0eG4KICAgIC8vICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgIGFzc2V0UmVjZWl2ZXI6IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLAogICAgLy8gICAgIGFzc2V0QW1vdW50OiAwLAogICAgLy8gICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgIH0pCiAgICAvLyAgIC5zdWJtaXQoKQogICAgaXR4bl9zdWJtaXQKICAgIHJldHN1YgoKb3B0SW5Ub0Fzc2V0X2Jvb2xfZmFsc2VAMzoKICAgIGludGNfMCAvLyAwCiAgICBiIG9wdEluVG9Bc3NldF9ib29sX21lcmdlQDQKCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3Quc3Rha2UoKSAtPiB2b2lkOgpzdGFrZToKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjI1LTIyNgogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgc3Rha2UoKTogdm9pZCB7CiAgICBwcm90byAwIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTQKICAgIC8vIHB1YmxpYyBhc3NldCA9IEdsb2JhbFN0YXRlPEFzc2V0Pih7IGluaXRpYWxWYWx1ZTogQXNzZXQoKSB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzEgLy8gImFzc2V0IgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18xIC8vICJhc3NldCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIyOQogICAgLy8gYXNzZXJ0KHRoaXMuYXNzZXQudmFsdWUgIT09IEFzc2V0KCksICdDb250cmFjdCBub3QgaW5pdGlhbGl6ZWQnKQogICAgYXNzZXJ0IC8vIENvbnRyYWN0IG5vdCBpbml0aWFsaXplZAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyMzIKICAgIC8vIGFzc2VydChHbG9iYWwuZ3JvdXBTaXplID09PSAyLCAnRXhwZWN0ZWQgMiB0eG5zIGluIGdyb3VwJykKICAgIGdsb2JhbCBHcm91cFNpemUKICAgIHB1c2hpbnQgMiAvLyAyCiAgICA9PQogICAgYXNzZXJ0IC8vIEV4cGVjdGVkIDIgdHhucyBpbiBncm91cAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyMzUKICAgIC8vIGNvbnN0IHhmZXJUeG4gPSBndHhuLkFzc2V0VHJhbnNmZXJUeG4oMCkKICAgIGludGNfMCAvLyAwCiAgICBndHhucyBUeXBlRW51bQogICAgZHVwCiAgICBpbnRjXzIgLy8gYXhmZXIKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBheGZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyMzYKICAgIC8vIGFzc2VydCh4ZmVyVHhuLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5Bc3NldFRyYW5zZmVyLCAnVHJhbnNhY3Rpb24gMCBtdXN0IGJlIGFzc2V0IHRyYW5zZmVyJykKICAgIGludGNfMiAvLyA0CiAgICA9PQogICAgYXNzZXJ0IC8vIFRyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyMzUKICAgIC8vIGNvbnN0IHhmZXJUeG4gPSBndHhuLkFzc2V0VHJhbnNmZXJUeG4oMCkKICAgIGludGNfMCAvLyAwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIzNwogICAgLy8gYXNzZXJ0KHhmZXJUeG4uYXNzZXRSZWNlaXZlciA9PT0gR2xvYmFsLmN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MsICdBc3NldCB0cmFuc2ZlciBtdXN0IGJlIHRvIGNvbnRyYWN0JykKICAgIGd0eG5zIEFzc2V0UmVjZWl2ZXIKICAgIGdsb2JhbCBDdXJyZW50QXBwbGljYXRpb25BZGRyZXNzCiAgICA9PQogICAgYXNzZXJ0IC8vIEFzc2V0IHRyYW5zZmVyIG11c3QgYmUgdG8gY29udHJhY3QKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjM1CiAgICAvLyBjb25zdCB4ZmVyVHhuID0gZ3R4bi5Bc3NldFRyYW5zZmVyVHhuKDApCiAgICBpbnRjXzAgLy8gMAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyMzgKICAgIC8vIGFzc2VydCh4ZmVyVHhuLmFzc2V0QW1vdW50ID4gMCwgJ011c3Qgc3Rha2Ugbm9uLXplcm8gYW1vdW50JykKICAgIGd0eG5zIEFzc2V0QW1vdW50CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGFzc2VydCAvLyBNdXN0IHN0YWtlIG5vbi16ZXJvIGFtb3VudAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyMzUKICAgIC8vIGNvbnN0IHhmZXJUeG4gPSBndHhuLkFzc2V0VHJhbnNmZXJUeG4oMCkKICAgIGludGNfMCAvLyAwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjIzOQogICAgLy8gYXNzZXJ0KHhmZXJUeG4ueGZlckFzc2V0ID09PSBhc3NldCwgJ0luY29ycmVjdCBhc3NldCBJRCcpCiAgICBndHhucyBYZmVyQXNzZXQKICAgID09CiAgICBhc3NlcnQgLy8gSW5jb3JyZWN0IGFzc2V0IElECiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU4CiAgICAvLyBwdWJsaWMgbWluaW11bVN0YWtlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjIDYgLy8gIm1pbmltdW1TdGFrZSIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjI0NAogICAgLy8gY29uc3Qgc2VuZGVyQWRkcmVzcyA9IFR4bi5zZW5kZXIKICAgIHR4biBTZW5kZXIKICAgIGR1cAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyNDcKICAgIC8vIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgY2FsbHN1YiBnZXRVc2VyU3Rha2VJbmZvCiAgICBkdXBuIDIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjUwCiAgICAvLyBpZiAoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPT09IDApIHsKICAgIGludGNfMCAvLyAwCiAgICBleHRyYWN0X3VpbnQ2NAogICAgYm56IHN0YWtlX2FmdGVyX2lmX2Vsc2VAMgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyNTEKICAgIC8vIGFzc2VydChzdGFrZUFtb3VudCA+PSBtaW5pbXVtU3Rha2UsICdJbml0aWFsIHN0YWtlIGJlbG93IG1pbmltdW0nKQogICAgZnJhbWVfZGlnIDAKICAgIGZyYW1lX2RpZyAxCiAgICA+PQogICAgYXNzZXJ0IC8vIEluaXRpYWwgc3Rha2UgYmVsb3cgbWluaW11bQogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyNTMKICAgIC8vIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZSA9IG5ldyBhcmM0LlVpbnRONjQoR2xvYmFsLmxhdGVzdFRpbWVzdGFtcCkKICAgIGdsb2JhbCBMYXRlc3RUaW1lc3RhbXAKICAgIGl0b2IKICAgIGZyYW1lX2RpZyAzCiAgICBzd2FwCiAgICByZXBsYWNlMiA4CiAgICBmcmFtZV9idXJ5IDQKCnN0YWtlX2FmdGVyX2lmX2Vsc2VAMjoKICAgIGZyYW1lX2RpZyA0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjI1NwogICAgLy8gc3Rha2VJbmZvLnN0YWtlZEFtb3VudCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKyBzdGFrZUFtb3VudCkKICAgIGR1cAogICAgaW50Y18wIC8vIDAKICAgIGV4dHJhY3RfdWludDY0CiAgICBmcmFtZV9kaWcgMAogICAgZHVwCiAgICBjb3ZlciAzCiAgICArCiAgICBpdG9iCiAgICByZXBsYWNlMiAwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjI1OAogICAgLy8gc3Rha2VJbmZvLmxhc3RTdGFrZVRpbWUgPSBuZXcgYXJjNC5VaW50TjY0KEdsb2JhbC5sYXRlc3RUaW1lc3RhbXApCiAgICBnbG9iYWwgTGF0ZXN0VGltZXN0YW1wCiAgICBpdG9iCiAgICByZXBsYWNlMiAxNgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyNjEKICAgIC8vIHN0YWtlSW5mby5yZXdhcmREZWJ0ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAqIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUpCiAgICBkdXAKICAgIGludGNfMCAvLyAwCiAgICBleHRyYWN0X3VpbnQ2NAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2MAogICAgLy8gcHVibGljIGFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjIDQgLy8gImFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjYxCiAgICAvLyBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgKgogICAgaXRvYgogICAgcmVwbGFjZTIgMzIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjY0CiAgICAvLyB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICBmcmFtZV9kaWcgMgogICAgc3dhcAogICAgY2FsbHN1YiBzdG9yZVVzZXJTdGFrZUluZm8KICAgIHBvcAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NgogICAgLy8gcHVibGljIHRvdGFsU3Rha2VkID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzIgLy8gInRvdGFsU3Rha2VkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjY3CiAgICAvLyB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHN0YWtlQW1vdW50CiAgICArCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU2CiAgICAvLyBwdWJsaWMgdG90YWxTdGFrZWQgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBieXRlY18yIC8vICJ0b3RhbFN0YWtlZCIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjY3CiAgICAvLyB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHN0YWtlQW1vdW50CiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo6QVNBU3Rha2luZ0NvbnRyYWN0LndpdGhkcmF3KGFtb3VudDogdWludDY0KSAtPiB2b2lkOgp3aXRoZHJhdzoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mjc0LTI3NQogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgd2l0aGRyYXcoYW1vdW50OiB1aW50NjQpOiB2b2lkIHsKICAgIHByb3RvIDEgMAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyNzYKICAgIC8vIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBUeG4uc2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICBkdXAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mjc3CiAgICAvLyBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcykKICAgIGNhbGxzdWIgZ2V0VXNlclN0YWtlSW5mbwogICAgZHVwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjI4MAogICAgLy8gYXNzZXJ0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlID4gMCwgJ05vIHN0YWtlIGZvdW5kJykKICAgIGludGNfMCAvLyAwCiAgICBleHRyYWN0X3VpbnQ2NAogICAgZHVwbiAyCiAgICBhc3NlcnQgLy8gTm8gc3Rha2UgZm91bmQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjgxCiAgICAvLyBhc3NlcnQoYW1vdW50IDw9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLCAnV2l0aGRyYXdhbCBhbW91bnQgZXhjZWVkcyBzdGFrZScpCiAgICBmcmFtZV9kaWcgLTEKICAgIGRpZyAxCiAgICA8PQogICAgYXNzZXJ0IC8vIFdpdGhkcmF3YWwgYW1vdW50IGV4Y2VlZHMgc3Rha2UKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MjgyCiAgICAvLyBhc3NlcnQoYW1vdW50ID4gMCwgJ1dpdGhkcmF3YWwgYW1vdW50IG11c3QgYmUgcG9zaXRpdmUnKQogICAgZnJhbWVfZGlnIC0xCiAgICBhc3NlcnQgLy8gV2l0aGRyYXdhbCBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZQogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyODYKICAgIC8vIGlmIChhbW91bnQgPCBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSkgewogICAgZnJhbWVfZGlnIC0xCiAgICA+CiAgICBieiB3aXRoZHJhd19hZnRlcl9pZl9lbHNlQDIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mjg3CiAgICAvLyBjb25zdCByZW1haW5pbmdTdGFrZTogdWludDY0ID0gc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgLSBhbW91bnQKICAgIGZyYW1lX2RpZyAyCiAgICBmcmFtZV9kaWcgLTEKICAgIC0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTgKICAgIC8vIHB1YmxpYyBtaW5pbXVtU3Rha2UgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWMgNiAvLyAibWluaW11bVN0YWtlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mjg5CiAgICAvLyBhc3NlcnQocmVtYWluaW5nU3Rha2UgPj0gbWluaW11bVN0YWtlLCAnUmVtYWluaW5nIHN0YWtlIHdvdWxkIGJlIGJlbG93IG1pbmltdW0nKQogICAgPj0KICAgIGFzc2VydCAvLyBSZW1haW5pbmcgc3Rha2Ugd291bGQgYmUgYmVsb3cgbWluaW11bQoKd2l0aGRyYXdfYWZ0ZXJfaWZfZWxzZUAyOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czoyOTMKICAgIC8vIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlIC0gYW1vdW50KQogICAgZnJhbWVfZGlnIDIKICAgIGZyYW1lX2RpZyAtMQogICAgLQogICAgaXRvYgogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIHJlcGxhY2UyIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mjk2CiAgICAvLyBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgZHVwCiAgICBpbnRjXzAgLy8gMAogICAgZXh0cmFjdF91aW50NjQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NjAKICAgIC8vIHB1YmxpYyBhY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZSA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlYyA0IC8vICJhY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZSIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjI5NgogICAgLy8gc3Rha2VJbmZvLnJld2FyZERlYnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICogdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSkKICAgICoKICAgIGl0b2IKICAgIHJlcGxhY2UyIDMyCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjI5OQogICAgLy8gdGhpcy5zdG9yZVVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcywgc3Rha2VJbmZvKQogICAgZnJhbWVfZGlnIDAKICAgIGR1cAogICAgdW5jb3ZlciAyCiAgICBjYWxsc3ViIHN0b3JlVXNlclN0YWtlSW5mbwogICAgcG9wCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU2CiAgICAvLyBwdWJsaWMgdG90YWxTdGFrZWQgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWNfMiAvLyAidG90YWxTdGFrZWQiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozMDIKICAgIC8vIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlIC0gYW1vdW50CiAgICBmcmFtZV9kaWcgLTEKICAgIC0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYKICAgIC8vIHB1YmxpYyB0b3RhbFN0YWtlZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGJ5dGVjXzIgLy8gInRvdGFsU3Rha2VkIgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozMDIKICAgIC8vIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlIC0gYW1vdW50CiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NAogICAgLy8gcHVibGljIGFzc2V0ID0gR2xvYmFsU3RhdGU8QXNzZXQ+KHsgaW5pdGlhbFZhbHVlOiBBc3NldCgpIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWNfMSAvLyAiYXNzZXQiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozMDYtMzEzCiAgICAvLyBpdHhuCiAgICAvLyAgIC5hc3NldFRyYW5zZmVyKHsKICAgIC8vICAgICBhc3NldFJlY2VpdmVyOiBzZW5kZXJBZGRyZXNzLAogICAgLy8gICAgIGFzc2V0QW1vdW50OiBhbW91bnQsCiAgICAvLyAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICBmZWU6IDEwMDAsCiAgICAvLyAgIH0pCiAgICAvLyAgIC5zdWJtaXQoKQogICAgaXR4bl9iZWdpbgogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIGZyYW1lX2RpZyAtMQogICAgaXR4bl9maWVsZCBBc3NldEFtb3VudAogICAgaXR4bl9maWVsZCBBc3NldFJlY2VpdmVyCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjMwNi0zMTIKICAgIC8vIGl0eG4KICAgIC8vICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgIGFzc2V0UmVjZWl2ZXI6IHNlbmRlckFkZHJlc3MsCiAgICAvLyAgICAgYXNzZXRBbW91bnQ6IGFtb3VudCwKICAgIC8vICAgICB4ZmVyQXNzZXQ6IGFzc2V0LAogICAgLy8gICAgIGZlZTogMTAwMCwKICAgIC8vICAgfSkKICAgIGludGNfMiAvLyA0CiAgICBpdHhuX2ZpZWxkIFR5cGVFbnVtCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjMxMQogICAgLy8gZmVlOiAxMDAwLAogICAgcHVzaGludCAxMDAwIC8vIDEwMDAKICAgIGl0eG5fZmllbGQgRmVlCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjMwNi0zMTMKICAgIC8vIGl0eG4KICAgIC8vICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgIGFzc2V0UmVjZWl2ZXI6IHNlbmRlckFkZHJlc3MsCiAgICAvLyAgICAgYXNzZXRBbW91bnQ6IGFtb3VudCwKICAgIC8vICAgICB4ZmVyQXNzZXQ6IGFzc2V0LAogICAgLy8gICAgIGZlZTogMTAwMCwKICAgIC8vICAgfSkKICAgIC8vICAgLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo6QVNBU3Rha2luZ0NvbnRyYWN0LmFkZFJld2FyZHMoKSAtPiB2b2lkOgphZGRSZXdhcmRzOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NQogICAgLy8gcHVibGljIGFkbWluQWRkcmVzcyA9IEdsb2JhbFN0YXRlPEFjY291bnQ+KHsgaW5pdGlhbFZhbHVlOiBBY2NvdW50KCl9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzAgLy8gImFkbWluQWRkcmVzcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjMyNQogICAgLy8gYXNzZXJ0KFR4bi5zZW5kZXIgPT09IGFkbWluQWRkciwgJ09ubHkgYWRtaW4gY2FuIGFkZCByZXdhcmRzJykKICAgIHR4biBTZW5kZXIKICAgID09CiAgICBhc3NlcnQgLy8gT25seSBhZG1pbiBjYW4gYWRkIHJld2FyZHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzI4CiAgICAvLyBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICBnbG9iYWwgR3JvdXBTaXplCiAgICBwdXNoaW50IDIgLy8gMgogICAgPT0KICAgIGFzc2VydCAvLyBFeHBlY3RlZCAyIHR4bnMgaW4gZ3JvdXAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTQKICAgIC8vIHB1YmxpYyBhc3NldCA9IEdsb2JhbFN0YXRlPEFzc2V0Pih7IGluaXRpYWxWYWx1ZTogQXNzZXQoKSB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzEgLy8gImFzc2V0IgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzMyCiAgICAvLyBjb25zdCB4ZmVyVHhuID0gZ3R4bi5Bc3NldFRyYW5zZmVyVHhuKDApCiAgICBpbnRjXzAgLy8gMAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGR1cAogICAgaW50Y18yIC8vIGF4ZmVyCiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgYXhmZXIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzMzCiAgICAvLyBhc3NlcnQoeGZlclR4bi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQXNzZXRUcmFuc2ZlciwgJ1RyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcicpCiAgICBpbnRjXzIgLy8gNAogICAgPT0KICAgIGFzc2VydCAvLyBUcmFuc2FjdGlvbiAwIG11c3QgYmUgYXNzZXQgdHJhbnNmZXIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzMyCiAgICAvLyBjb25zdCB4ZmVyVHhuID0gZ3R4bi5Bc3NldFRyYW5zZmVyVHhuKDApCiAgICBpbnRjXzAgLy8gMAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozMzQKICAgIC8vIGFzc2VydCh4ZmVyVHhuLmFzc2V0UmVjZWl2ZXIgPT09IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLCAnQXNzZXQgdHJhbnNmZXIgbXVzdCBiZSB0byBjb250cmFjdCcpCiAgICBndHhucyBBc3NldFJlY2VpdmVyCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgPT0KICAgIGFzc2VydCAvLyBBc3NldCB0cmFuc2ZlciBtdXN0IGJlIHRvIGNvbnRyYWN0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjMzMgogICAgLy8gY29uc3QgeGZlclR4biA9IGd0eG4uQXNzZXRUcmFuc2ZlclR4bigwKQogICAgaW50Y18wIC8vIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzM1CiAgICAvLyBhc3NlcnQoeGZlclR4bi5hc3NldEFtb3VudCA+IDAsICdNdXN0IHByb3ZpZGUgbm9uLXplcm8gcmV3YXJkcycpCiAgICBndHhucyBBc3NldEFtb3VudAogICAgZHVwCiAgICBhc3NlcnQgLy8gTXVzdCBwcm92aWRlIG5vbi16ZXJvIHJld2FyZHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzMyCiAgICAvLyBjb25zdCB4ZmVyVHhuID0gZ3R4bi5Bc3NldFRyYW5zZmVyVHhuKDApCiAgICBpbnRjXzAgLy8gMAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozMzYKICAgIC8vIGFzc2VydCh4ZmVyVHhuLnhmZXJBc3NldCA9PT0gYXNzZXQsICdJbmNvcnJlY3QgYXNzZXQgSUQnKQogICAgZ3R4bnMgWGZlckFzc2V0CiAgICB1bmNvdmVyIDIKICAgID09CiAgICBhc3NlcnQgLy8gSW5jb3JyZWN0IGFzc2V0IElECiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU5CiAgICAvLyBwdWJsaWMgcmV3YXJkUG9vbCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18zIC8vICJyZXdhcmRQb29sIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzM5CiAgICAvLyB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSB0aGlzLnJld2FyZFBvb2wudmFsdWUgKyB4ZmVyVHhuLmFzc2V0QW1vdW50CiAgICArCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU5CiAgICAvLyBwdWJsaWMgcmV3YXJkUG9vbCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGJ5dGVjXzMgLy8gInJld2FyZFBvb2wiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjMzOQogICAgLy8gdGhpcy5yZXdhcmRQb29sLnZhbHVlID0gdGhpcy5yZXdhcmRQb29sLnZhbHVlICsgeGZlclR4bi5hc3NldEFtb3VudAogICAgc3dhcAogICAgYXBwX2dsb2JhbF9wdXQKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6OkFTQVN0YWtpbmdDb250cmFjdC5nZXRDdXJyZW50QVBZKCkgLT4gdWludDY0OgpnZXRDdXJyZW50QVBZOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozNDUtMzQ2CiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRDdXJyZW50QVBZKCk6IHVpbnQ2NCB7CiAgICBwcm90byAwIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYKICAgIC8vIHB1YmxpYyB0b3RhbFN0YWtlZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18yIC8vICJ0b3RhbFN0YWtlZCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBzd2FwCiAgICBkdXAKICAgIHVuY292ZXIgMgogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozNDkKICAgIC8vIGlmICh0b3RhbFN0YWtlZCA9PT0gMCkgewogICAgYm56IGdldEN1cnJlbnRBUFlfYWZ0ZXJfaWZfZWxzZUAyCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjM1MAogICAgLy8gcmV0dXJuIDAgLy8gUmV0dXJuIDAgaWYgbm8gdG9rZW5zIHN0YWtlZAogICAgaW50Y18wIC8vIDAKICAgIHN3YXAKICAgIHJldHN1YgoKZ2V0Q3VycmVudEFQWV9hZnRlcl9pZl9lbHNlQDI6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjYzCiAgICAvLyBwdWJsaWMgd2Vla2x5UmV3YXJkcyA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlYyA3IC8vICJ3ZWVrbHlSZXdhcmRzIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzU0CiAgICAvLyBjb25zdCBhbm51YWxSZXdhcmRzOiB1aW50NjQgPSA1MiAqIHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZQogICAgcHVzaGludCA1MiAvLyA1MgogICAgKgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozNTcKICAgIC8vIGNvbnN0IGFweTogdWludDY0ID0gKGFubnVhbFJld2FyZHMgKiAxMDApIC8gdG90YWxTdGFrZWQKICAgIHB1c2hpbnQgMTAwIC8vIDEwMAogICAgKgogICAgZnJhbWVfZGlnIDAKICAgIC8KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzU5CiAgICAvLyByZXR1cm4gYXB5CiAgICBzd2FwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3QuZ2V0UGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3M6IGJ5dGVzKSAtPiB1aW50NjQ6CmdldFBlbmRpbmdSZXdhcmRzOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czozNjUtMzY2CiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHVpbnQ2NCB7CiAgICBwcm90byAxIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzY3CiAgICAvLyByZXR1cm4gdGhpcy5jYWxjdWxhdGVQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzcykKICAgIGZyYW1lX2RpZyAtMQogICAgY2FsbHN1YiBjYWxjdWxhdGVQZW5kaW5nUmV3YXJkcwogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo6QVNBU3Rha2luZ0NvbnRyYWN0LnRyaWdnZXJSZXdhcmREaXN0cmlidXRpb24oKSAtPiB2b2lkOgp0cmlnZ2VyUmV3YXJkRGlzdHJpYnV0aW9uOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NQogICAgLy8gcHVibGljIGFkbWluQWRkcmVzcyA9IEdsb2JhbFN0YXRlPEFjY291bnQ+KHsgaW5pdGlhbFZhbHVlOiBBY2NvdW50KCl9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzAgLy8gImFkbWluQWRkcmVzcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjM3OQogICAgLy8gYXNzZXJ0KFR4bi5zZW5kZXIgPT09IGFkbWluQWRkciwgJ09ubHkgYWRtaW4gY2FuIHRyaWdnZXIgZGlzdHJpYnV0aW9uJykKICAgIHR4biBTZW5kZXIKICAgID09CiAgICBhc3NlcnQgLy8gT25seSBhZG1pbiBjYW4gdHJpZ2dlciBkaXN0cmlidXRpb24KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6MzgyCiAgICAvLyB0aGlzLnVwZGF0ZVJld2FyZHMoKQogICAgY2FsbHN1YiB1cGRhdGVSZXdhcmRzCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3QudXBkYXRlQWRtaW4obmV3QWRtaW5BZGRyZXNzOiBieXRlcykgLT4gdm9pZDoKdXBkYXRlQWRtaW46CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjM5NS0zOTYKICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHVwZGF0ZUFkbWluKG5ld0FkbWluQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgcHJvdG8gMSAwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU1CiAgICAvLyBwdWJsaWMgYWRtaW5BZGRyZXNzID0gR2xvYmFsU3RhdGU8QWNjb3VudD4oeyBpbml0aWFsVmFsdWU6IEFjY291bnQoKX0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWNfMCAvLyAiYWRtaW5BZGRyZXNzIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6Mzk5CiAgICAvLyBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluJykKICAgIHR4biBTZW5kZXIKICAgID09CiAgICBhc3NlcnQgLy8gT25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU1CiAgICAvLyBwdWJsaWMgYWRtaW5BZGRyZXNzID0gR2xvYmFsU3RhdGU8QWNjb3VudD4oeyBpbml0aWFsVmFsdWU6IEFjY291bnQoKX0pCiAgICBieXRlY18wIC8vICJhZG1pbkFkZHJlc3MiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQwMgogICAgLy8gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUgPSBuZXdBZG1pbkFkZHJlc3MKICAgIGZyYW1lX2RpZyAtMQogICAgYXBwX2dsb2JhbF9wdXQKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6OkFTQVN0YWtpbmdDb250cmFjdC5nZXRVc2VyU3RhdHModXNlckFkZHJlc3M6IGJ5dGVzKSAtPiBieXRlczoKZ2V0VXNlclN0YXRzOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MDgtNDA5CiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRVc2VyU3RhdHModXNlckFkZHJlc3M6IEFjY291bnQpOiBBcnJheTx1aW50NjQ+IHsKICAgIHByb3RvIDEgMQogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MTAKICAgIC8vIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcykKICAgIGZyYW1lX2RpZyAtMQogICAgY2FsbHN1YiBnZXRVc2VyU3Rha2VJbmZvCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxMQogICAgLy8gY29uc3QgcGVuZGluZ1Jld2FyZHMgPSB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgZnJhbWVfZGlnIC0xCiAgICBjYWxsc3ViIGNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxNAogICAgLy8gc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsCiAgICBkaWcgMQogICAgaW50Y18wIC8vIDAKICAgIGV4dHJhY3RfdWludDY0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxNQogICAgLy8gc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIGRpZyAyCiAgICBpbnRjXzMgLy8gOAogICAgZXh0cmFjdF91aW50NjQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDE2CiAgICAvLyBzdGFrZUluZm8ubGFzdFN0YWtlVGltZS5uYXRpdmUsCiAgICBkaWcgMwogICAgcHVzaGludCAxNiAvLyAxNgogICAgZXh0cmFjdF91aW50NjQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDE3CiAgICAvLyBzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkLm5hdGl2ZSwKICAgIGRpZyA0CiAgICBwdXNoaW50IDI0IC8vIDI0CiAgICBleHRyYWN0X3VpbnQ2NAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MTkKICAgIC8vIHN0YWtlSW5mby5yZXdhcmREZWJ0Lm5hdGl2ZSwKICAgIGRpZyA1CiAgICBwdXNoaW50IDMyIC8vIDMyCiAgICBleHRyYWN0X3VpbnQ2NAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MjAKICAgIC8vIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcy5uYXRpdmUsCiAgICB1bmNvdmVyIDYKICAgIHB1c2hpbnQgNDAgLy8gNDAKICAgIGV4dHJhY3RfdWludDY0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxNAogICAgLy8gc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsCiAgICB1bmNvdmVyIDUKICAgIGl0b2IKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDE1CiAgICAvLyBzdGFrZUluZm8uZmlyc3RTdGFrZVRpbWUubmF0aXZlLAogICAgdW5jb3ZlciA1CiAgICBpdG9iCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxNC00MjAKICAgIC8vIHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLAogICAgLy8gc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby5sYXN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby50b3RhbFJld2FyZHNFYXJuZWQubmF0aXZlLAogICAgLy8gcGVuZGluZ1Jld2FyZHMsCiAgICAvLyBzdGFrZUluZm8ucmV3YXJkRGVidC5uYXRpdmUsCiAgICAvLyBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMubmF0aXZlLAogICAgY29uY2F0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxNgogICAgLy8gc3Rha2VJbmZvLmxhc3RTdGFrZVRpbWUubmF0aXZlLAogICAgdW5jb3ZlciA0CiAgICBpdG9iCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxNC00MjAKICAgIC8vIHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLAogICAgLy8gc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby5sYXN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby50b3RhbFJld2FyZHNFYXJuZWQubmF0aXZlLAogICAgLy8gcGVuZGluZ1Jld2FyZHMsCiAgICAvLyBzdGFrZUluZm8ucmV3YXJkRGVidC5uYXRpdmUsCiAgICAvLyBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMubmF0aXZlLAogICAgY29uY2F0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxNwogICAgLy8gc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUsCiAgICB1bmNvdmVyIDMKICAgIGl0b2IKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDE0LTQyMAogICAgLy8gc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsCiAgICAvLyBzdGFrZUluZm8uZmlyc3RTdGFrZVRpbWUubmF0aXZlLAogICAgLy8gc3Rha2VJbmZvLmxhc3RTdGFrZVRpbWUubmF0aXZlLAogICAgLy8gc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUsCiAgICAvLyBwZW5kaW5nUmV3YXJkcywKICAgIC8vIHN0YWtlSW5mby5yZXdhcmREZWJ0Lm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcy5uYXRpdmUsCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDE4CiAgICAvLyBwZW5kaW5nUmV3YXJkcywKICAgIHVuY292ZXIgMwogICAgaXRvYgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MTQtNDIwCiAgICAvLyBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyBzdGFrZUluZm8ubGFzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyBzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkLm5hdGl2ZSwKICAgIC8vIHBlbmRpbmdSZXdhcmRzLAogICAgLy8gc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlLAogICAgLy8gc3Rha2VJbmZvLnBlbmRpbmdSZXdhcmRzLm5hdGl2ZSwKICAgIGNvbmNhdAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MTkKICAgIC8vIHN0YWtlSW5mby5yZXdhcmREZWJ0Lm5hdGl2ZSwKICAgIHVuY292ZXIgMgogICAgaXRvYgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MTQtNDIwCiAgICAvLyBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyBzdGFrZUluZm8ubGFzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyBzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkLm5hdGl2ZSwKICAgIC8vIHBlbmRpbmdSZXdhcmRzLAogICAgLy8gc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlLAogICAgLy8gc3Rha2VJbmZvLnBlbmRpbmdSZXdhcmRzLm5hdGl2ZSwKICAgIGNvbmNhdAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MjAKICAgIC8vIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcy5uYXRpdmUsCiAgICBzd2FwCiAgICBpdG9iCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQxNC00MjAKICAgIC8vIHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLAogICAgLy8gc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby5sYXN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vIHN0YWtlSW5mby50b3RhbFJld2FyZHNFYXJuZWQubmF0aXZlLAogICAgLy8gcGVuZGluZ1Jld2FyZHMsCiAgICAvLyBzdGFrZUluZm8ucmV3YXJkRGVidC5uYXRpdmUsCiAgICAvLyBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMubmF0aXZlLAogICAgY29uY2F0CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18zIC8vIDgKICAgIC8KICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDIzCiAgICAvLyByZXR1cm4gcmVzdWx0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3QuZ2V0Q29udHJhY3RTdGF0cygpIC0+IGJ5dGVzOgpnZXRDb250cmFjdFN0YXRzOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0MzEKICAgIC8vIGNvbnN0IGN1cnJlbnRBUFkgPSB0aGlzLmdldEN1cnJlbnRBUFkoKQogICAgY2FsbHN1YiBnZXRDdXJyZW50QVBZCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU0CiAgICAvLyBwdWJsaWMgYXNzZXQgPSBHbG9iYWxTdGF0ZTxBc3NldD4oeyBpbml0aWFsVmFsdWU6IEFzc2V0KCkgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18xIC8vICJhc3NldCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU2CiAgICAvLyBwdWJsaWMgdG90YWxTdGFrZWQgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWNfMiAvLyAidG90YWxTdGFrZWQiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NwogICAgLy8gcHVibGljIGxhc3RSZXdhcmRUaW1lID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjIDUgLy8gImxhc3RSZXdhcmRUaW1lIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NjQKICAgIC8vIHB1YmxpYyByZXdhcmRQZXJpb2QgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWMgOCAvLyAicmV3YXJkUGVyaW9kIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTgKICAgIC8vIHB1YmxpYyBtaW5pbXVtU3Rha2UgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWMgNiAvLyAibWluaW11bVN0YWtlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTkKICAgIC8vIHB1YmxpYyByZXdhcmRQb29sID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzMgLy8gInJld2FyZFBvb2wiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2MAogICAgLy8gcHVibGljIGFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjIDQgLy8gImFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTQKICAgIC8vIHB1YmxpYyBhc3NldCA9IEdsb2JhbFN0YXRlPEFzc2V0Pih7IGluaXRpYWxWYWx1ZTogQXNzZXQoKSB9KQogICAgdW5jb3ZlciA2CiAgICBpdG9iCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU2CiAgICAvLyBwdWJsaWMgdG90YWxTdGFrZWQgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICB1bmNvdmVyIDYKICAgIGl0b2IKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYtNDM2CiAgICAvLyBwdWJsaWMgdG90YWxTdGFrZWQgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgbGFzdFJld2FyZFRpbWUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgbWluaW11bVN0YWtlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIHJld2FyZFBvb2wgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyAKICAgIC8vIC8vIENvbnN0YW50cyBmb3IgZml4ZWQgcmV3YXJkIHN5c3RlbSAtIG5vdyBhcyBHbG9iYWxTdGF0ZSBmb3IgZmxleGliaWxpdHkKICAgIC8vIHB1YmxpYyB3ZWVrbHlSZXdhcmRzID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIHJld2FyZFBlcmlvZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIAogICAgLy8gcHVibGljIHN0YWtlcnMgPSBCb3hNYXA8QWNjb3VudCwgVXNlclN0YWtlSW5mbz4oeyBrZXlQcmVmaXg6ICdzdGFrZXJzJyB9KQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byByZWFkIHVzZXIgc3Rha2UgaW5mbyBmcm9tIGJveCBzdG9yYWdlCiAgICAvLyAgKi8KICAgIC8vIHB1YmxpYyBnZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogVXNlclN0YWtlSW5mbyB7CiAgICAvLyAgIGNvbnN0IHVzZXJCb3ggPSB0aGlzLnN0YWtlcnModXNlckFkZHJlc3MpCiAgICAvLyAKICAgIC8vICAgaWYgKHVzZXJCb3guZXhpc3RzKSB7CiAgICAvLyAgICAgcmV0dXJuIHVzZXJCb3gudmFsdWUuY29weSgpCiAgICAvLyAgIH0gZWxzZSB7CiAgICAvLyAgICAgcmV0dXJuIG5ldyBVc2VyU3Rha2VJbmZvKHsKICAgIC8vICAgICAgIHN0YWtlZEFtb3VudDogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIGZpcnN0U3Rha2VUaW1lOiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICAgICAgbGFzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIHRvdGFsUmV3YXJkc0Vhcm5lZDogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIHJld2FyZERlYnQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICBwZW5kaW5nUmV3YXJkczogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICB9KQogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSGVscGVyIGZ1bmN0aW9uIHRvIHN0b3JlIHVzZXIgc3Rha2UgaW5mbyBpbiBib3ggc3RvcmFnZQogICAgLy8gICovCiAgICAvLyBwdWJsaWMgc3RvcmVVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50LCBzdGFrZUluZm86IFVzZXJTdGFrZUluZm8pOiB2b2lkIHsKICAgIC8vICAgdGhpcy5zdGFrZXJzKHVzZXJBZGRyZXNzKS52YWx1ZSA9IHN0YWtlSW5mby5jb3B5KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUgaWYgcmV3YXJkIHBlcmlvZCBoYXMgcGFzc2VkCiAgICAvLyAgKi8KICAgIC8vIHByaXZhdGUgdXBkYXRlUmV3YXJkcygpOiB2b2lkIHsKICAgIC8vICAgY29uc3QgY3VycmVudFRpbWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICAvLyAgIGNvbnN0IGxhc3RSZXdhcmQgPSB0aGlzLmxhc3RSZXdhcmRUaW1lLnZhbHVlCiAgICAvLyAgIGNvbnN0IHJld2FyZFBlcmlvZCA9IHRoaXMucmV3YXJkUGVyaW9kLnZhbHVlCiAgICAvLyAKICAgIC8vICAgLy8gQ2hlY2sgaWYgYSBmdWxsIHJld2FyZCBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICBpZiAoY3VycmVudFRpbWUgPj0gbGFzdFJld2FyZCArIHJld2FyZFBlcmlvZCAmJiB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID4gMCkgewogICAgLy8gICAgIC8vIENhbGN1bGF0ZSBob3cgbWFueSBjb21wbGV0ZSBwZXJpb2RzIGhhdmUgcGFzc2VkCiAgICAvLyAgICAgY29uc3QgcGVyaW9kc1Bhc3NlZDogdWludDY0ID0gKGN1cnJlbnRUaW1lIC0gbGFzdFJld2FyZCkgLyByZXdhcmRQZXJpb2QKICAgIC8vIAogICAgLy8gICAgIC8vIFVwZGF0ZSBhY2N1bXVsYXRlZCByZXdhcmRzIHBlciBzaGFyZQogICAgLy8gICAgIGNvbnN0IHJld2FyZFBlclBlcmlvZCA9IHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZQogICAgLy8gICAgIGNvbnN0IHRvdGFsUmV3YXJkczogdWludDY0ID0gcmV3YXJkUGVyUGVyaW9kICogcGVyaW9kc1Bhc3NlZAogICAgLy8gCiAgICAvLyAgICAgLy8gU2ltcGxlIGRpdmlzaW9uIC0gcmV3YXJkcyBwZXIgdG9rZW4gc3Rha2VkCiAgICAvLyAgICAgY29uc3QgdG90YWxTdGFrZWQgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlCiAgICAvLyAgICAgY29uc3QgcmV3YXJkUGVyU2hhcmU6IHVpbnQ2NCA9IHRvdGFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUKICAgIC8vICAgICB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlID0gdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSArIHJld2FyZFBlclNoYXJlCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgbGFzdCByZXdhcmQgdGltZSB0byB0aGUgbW9zdCByZWNlbnQgY29tcGxldGUgcGVyaW9kCiAgICAvLyAgICAgdGhpcy5sYXN0UmV3YXJkVGltZS52YWx1ZSA9IGxhc3RSZXdhcmQgKyAocGVyaW9kc1Bhc3NlZCAqIHJld2FyZFBlcmlvZCkKICAgIC8vIAogICAgLy8gICAgIC8vIERlZHVjdCByZXdhcmRzIGZyb20gcG9vbAogICAgLy8gICAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IHRoaXMucmV3YXJkUG9vbC52YWx1ZSAtIHRvdGFsUmV3YXJkcwogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogQ2FsY3VsYXRlIHBlbmRpbmcgcmV3YXJkcyBmb3IgYSB1c2VyCiAgICAvLyAgKi8KICAgIC8vIHByaXZhdGUgY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3M6IEFjY291bnQpOiB1aW50NjQgewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAKICAgIC8vICAgaWYgKHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlID09PSAwKSB7CiAgICAvLyAgICAgcmV0dXJuIDAKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHVzZXJTdGFrZSA9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlCiAgICAvLyAgIGNvbnN0IGFjY1Jld2FyZHNQZXJTaGFyZSA9IHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUKICAgIC8vICAgY29uc3QgdXNlclJld2FyZERlYnQgPSBzdGFrZUluZm8ucmV3YXJkRGVidC5uYXRpdmUKICAgIC8vIAogICAgLy8gICAvLyBTaW1wbGUgY2FsY3VsYXRpb24gd2l0aG91dCBwcmVjaXNpb24KICAgIC8vICAgY29uc3QgdG90YWxFYXJuZWQ6IHVpbnQ2NCA9IHVzZXJTdGFrZSAqIGFjY1Jld2FyZHNQZXJTaGFyZQogICAgLy8gICBjb25zdCBwZW5kaW5nUmV3YXJkczogdWludDY0ID0gdG90YWxFYXJuZWQgPiB1c2VyUmV3YXJkRGVidCA/IHRvdGFsRWFybmVkIC0gdXNlclJld2FyZERlYnQgOiAwCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIHBlbmRpbmdSZXdhcmRzCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSGVscGVyIGZ1bmN0aW9uIHRvIGNvbXBvdW5kIHJld2FyZHMgZm9yIGEgdXNlcgogICAgLy8gICovCiAgICAvLyBwcml2YXRlIGNvbXBvdW5kUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA+IDApIHsKICAgIC8vICAgICBjb25zdCBwZW5kaW5nUmV3YXJkcyA9IHRoaXMuY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3MpCiAgICAvLyAgICAgaWYgKHBlbmRpbmdSZXdhcmRzID4gMCkgewogICAgLy8gICAgICAgLy8gQWRkIHJld2FyZHMgdG8gc3Rha2UKICAgIC8vICAgICAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICsgcGVuZGluZ1Jld2FyZHMpCiAgICAvLyAgICAgICBzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkLm5hdGl2ZSArIHBlbmRpbmdSZXdhcmRzKQogICAgLy8gICAgICAgc3Rha2VJbmZvLnJld2FyZERlYnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICogdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSkKICAgIC8vICAgICAgIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcyA9IG5ldyBhcmM0LlVpbnRONjQoMCkKICAgIC8vICAgICAgIHRoaXMuc3RvcmVVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgICAgIC8vIFVwZGF0ZSB0b3RhbCBzdGFrZWQKICAgIC8vICAgICAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlICsgcGVuZGluZ1Jld2FyZHMKICAgIC8vICAgICB9CiAgICAvLyAgIH0KICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBJbml0aWFsaXplIHRoZSBjb250cmFjdCB3aXRoIHRoZSBBU0EgdG9rZW4gSUQgYW5kIG90aGVyIHBhcmFtZXRlcnMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgaW5pdGlhbGl6ZSgKICAgIC8vICAgYXNzZXQ6IEFzc2V0LAogICAgLy8gICBhZG1pbkFkZHJlc3M6IEFjY291bnQsCiAgICAvLyAgIG1pbmltdW1TdGFrZTogdWludDY0LAogICAgLy8gICB3ZWVrbHlSZXdhcmRzOiB1aW50NjQsCiAgICAvLyAgIHJld2FyZFBlcmlvZDogdWludDY0LAogICAgLy8gKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGlzIG9ubHkgY2FsbGVkIGR1cmluZyBjb250cmFjdCBjcmVhdGlvbgogICAgLy8gICBhc3NlcnQodGhpcy5hc3NldC52YWx1ZSA9PT0gQXNzZXQoKSwgJ0FscmVhZHkgaW5pdGlhbGl6ZWQnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IHRoZSBjcmVhdG9yIGNhbiBpbml0aWFsaXplCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBHbG9iYWwuY3JlYXRvckFkZHJlc3MsICdPbmx5IGNyZWF0b3IgY2FuIGluaXRpYWxpemUnKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHRoZSBpbml0aWFsIHBhcmFtZXRlcnMKICAgIC8vICAgdGhpcy5hc3NldC52YWx1ZSA9IGFzc2V0CiAgICAvLyAgIHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlID0gYWRtaW5BZGRyZXNzCiAgICAvLyAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSAwCiAgICAvLyAgIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICAvLyAgIHRoaXMubWluaW11bVN0YWtlLnZhbHVlID0gbWluaW11bVN0YWtlCiAgICAvLyAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IDAKICAgIC8vICAgdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSA9IDAKICAgIC8vIAogICAgLy8gICAvLyBTZXQgcmV3YXJkIHN5c3RlbSBwYXJhbWV0ZXJzCiAgICAvLyAgIHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZSA9IHdlZWtseVJld2FyZHMKICAgIC8vICAgdGhpcy5yZXdhcmRQZXJpb2QudmFsdWUgPSByZXdhcmRQZXJpb2QKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBPcHQgdGhlIGNvbnRyYWN0IGludG8gdGhlIEFTQQogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyBvcHRJblRvQXNzZXQoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IHRoZSBjcmVhdG9yIG9yIGFkbWluIGNhbiBvcHQgaW4KICAgIC8vICAgY29uc3QgYWRtaW5BZGRyID0gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUKICAgIC8vICAgYXNzZXJ0KFR4bi5zZW5kZXIgPT09IEdsb2JhbC5jcmVhdG9yQWRkcmVzcyB8fCBUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGNyZWF0b3Igb3IgYWRtaW4gY2FuIG9wdCBpbicpCiAgICAvLyAKICAgIC8vICAgLy8gT3B0IHRoZSBjb250cmFjdCBpbnRvIHRoZSBBU0EKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGl0eG4KICAgIC8vICAgICAuYXNzZXRUcmFuc2Zlcih7CiAgICAvLyAgICAgICBhc3NldFJlY2VpdmVyOiBHbG9iYWwuY3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcywKICAgIC8vICAgICAgIGFzc2V0QW1vdW50OiAwLAogICAgLy8gICAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICB9KQogICAgLy8gICAgIC5zdWJtaXQoKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFN0YWtlIHRva2VucwogICAgLy8gICogUmVxdWlyZXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uCiAgICAvLyAgKiBBdXRvbWF0aWNhbGx5IGNsYWltcyBwZW5kaW5nIHJld2FyZHMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgc3Rha2UoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSB0aGUgY29udHJhY3QgaGFzIG9wdGVkIGludG8gdGhlIEFTQQogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgYXNzZXJ0KHRoaXMuYXNzZXQudmFsdWUgIT09IEFzc2V0KCksICdDb250cmFjdCBub3QgaW5pdGlhbGl6ZWQnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGNhbGwgaGFzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbgogICAgLy8gICBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBBU0EgdHJhbnNmZXIgZGV0YWlscwogICAgLy8gICBjb25zdCB4ZmVyVHhuID0gZ3R4bi5Bc3NldFRyYW5zZmVyVHhuKDApCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5Bc3NldFRyYW5zZmVyLCAnVHJhbnNhY3Rpb24gMCBtdXN0IGJlIGFzc2V0IHRyYW5zZmVyJykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4uYXNzZXRSZWNlaXZlciA9PT0gR2xvYmFsLmN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MsICdBc3NldCB0cmFuc2ZlciBtdXN0IGJlIHRvIGNvbnRyYWN0JykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4uYXNzZXRBbW91bnQgPiAwLCAnTXVzdCBzdGFrZSBub24temVybyBhbW91bnQnKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi54ZmVyQXNzZXQgPT09IGFzc2V0LCAnSW5jb3JyZWN0IGFzc2V0IElEJykKICAgIC8vIAogICAgLy8gICAvLyBHZXQgdGhlIHN0YWtlIGFtb3VudCBmcm9tIHRoZSB0cmFuc2FjdGlvbgogICAgLy8gICBjb25zdCBzdGFrZUFtb3VudCA9IHhmZXJUeG4uYXNzZXRBbW91bnQKICAgIC8vICAgY29uc3QgbWluaW11bVN0YWtlID0gdGhpcy5taW5pbXVtU3Rha2UudmFsdWUKICAgIC8vICAgY29uc3Qgc2VuZGVyQWRkcmVzcyA9IFR4bi5zZW5kZXIKICAgIC8vIAogICAgLy8gICAvLyBHZXQgdGhlIGN1cnJlbnQgdXNlciBzdGFrZSBpbmZvCiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIC8vIElmIHRoaXMgaXMgYSBuZXcgc3Rha2UsIGVuc3VyZSBpdCBtZWV0cyBtaW5pbXVtCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA9PT0gMCkgewogICAgLy8gICAgIGFzc2VydChzdGFrZUFtb3VudCA+PSBtaW5pbXVtU3Rha2UsICdJbml0aWFsIHN0YWtlIGJlbG93IG1pbmltdW0nKQogICAgLy8gICAgIC8vIFNldCB0aGUgZmlyc3Qgc3Rha2UgdGltZSAodGhpcyBuZXZlciBjaGFuZ2VzIGFmdGVyIGluaXRpYWwgc3Rha2UpCiAgICAvLyAgICAgc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lID0gbmV3IGFyYzQuVWludE42NChHbG9iYWwubGF0ZXN0VGltZXN0YW1wKQogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHN0YWtlIGluZm8gd2l0aCBuZXcgYW1vdW50CiAgICAvLyAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICsgc3Rha2VBbW91bnQpCiAgICAvLyAgIHN0YWtlSW5mby5sYXN0U3Rha2VUaW1lID0gbmV3IGFyYzQuVWludE42NChHbG9iYWwubGF0ZXN0VGltZXN0YW1wKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSByZXdhcmQgZGVidAogICAgLy8gICBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHVwZGF0ZWQgc3Rha2UgaW5mbwogICAgLy8gICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIGdsb2JhbCBzdGF0ZQogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHN0YWtlQW1vdW50CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogV2l0aGRyYXcgc3Rha2VkIHRva2VucwogICAgLy8gICogQXV0b21hdGljYWxseSBjbGFpbXMgcGVuZGluZyByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHdpdGhkcmF3KGFtb3VudDogdWludDY0KTogdm9pZCB7CiAgICAvLyAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBUeG4uc2VuZGVyCiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB1c2VyIGhhcyBlbm91Z2ggc3Rha2VkCiAgICAvLyAgIGFzc2VydChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA+IDAsICdObyBzdGFrZSBmb3VuZCcpCiAgICAvLyAgIGFzc2VydChhbW91bnQgPD0gc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsICdXaXRoZHJhd2FsIGFtb3VudCBleGNlZWRzIHN0YWtlJykKICAgIC8vICAgYXNzZXJ0KGFtb3VudCA+IDAsICdXaXRoZHJhd2FsIGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlJykKICAgIC8vIAogICAgLy8gICAvLyBJZiB3aXRoZHJhd2luZyBhbGwsIG5vIG5lZWQgdG8gY2hlY2sgbWluaW11bSByZW1haW5pbmcKICAgIC8vICAgLy8gSWYgcGFydGlhbCB3aXRoZHJhd2FsLCBlbnN1cmUgcmVtYWluaW5nIHN0YWtlIG1lZXRzIG1pbmltdW0KICAgIC8vICAgaWYgKGFtb3VudCA8IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlKSB7CiAgICAvLyAgICAgY29uc3QgcmVtYWluaW5nU3Rha2U6IHVpbnQ2NCA9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlIC0gYW1vdW50CiAgICAvLyAgICAgY29uc3QgbWluaW11bVN0YWtlID0gdGhpcy5taW5pbXVtU3Rha2UudmFsdWUKICAgIC8vICAgICBhc3NlcnQocmVtYWluaW5nU3Rha2UgPj0gbWluaW11bVN0YWtlLCAnUmVtYWluaW5nIHN0YWtlIHdvdWxkIGJlIGJlbG93IG1pbmltdW0nKQogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHN0YWtlIGluZm8KICAgIC8vICAgc3Rha2VJbmZvLnN0YWtlZEFtb3VudCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgLSBhbW91bnQpCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHJld2FyZCBkZWJ0CiAgICAvLyAgIHN0YWtlSW5mby5yZXdhcmREZWJ0ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAqIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUpCiAgICAvLyAKICAgIC8vICAgLy8gU3RvcmUgdXBkYXRlZCBzdGFrZSBpbmZvCiAgICAvLyAgIHRoaXMuc3RvcmVVc2VyU3Rha2VJbmZvKHNlbmRlckFkZHJlc3MsIHN0YWtlSW5mbykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgZ2xvYmFsIHN0YXRlCiAgICAvLyAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlIC0gYW1vdW50CiAgICAvLyAKICAgIC8vICAgLy8gVHJhbnNmZXIgdG9rZW5zIGJhY2sgdG8gdXNlcgogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgaXR4bgogICAgLy8gICAgIC5hc3NldFRyYW5zZmVyKHsKICAgIC8vICAgICAgIGFzc2V0UmVjZWl2ZXI6IHNlbmRlckFkZHJlc3MsCiAgICAvLyAgICAgICBhc3NldEFtb3VudDogYW1vdW50LAogICAgLy8gICAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICAgIGZlZTogMTAwMCwKICAgIC8vICAgICB9KQogICAgLy8gICAgIC5zdWJtaXQoKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEFkZCByZXdhcmRzIHRvIHRoZSByZXdhcmQgcG9vbAogICAgLy8gICogT25seSB0aGUgYWRtaW4gY2FuIGNhbGwgdGhpcwogICAgLy8gICogUmVxdWlyZXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggdGhlIHJld2FyZHMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgYWRkUmV3YXJkcygpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIGFkZCByZXdhcmRzCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiBhZGQgcmV3YXJkcycpCiAgICAvLyAKICAgIC8vICAgLy8gRW5zdXJlIHRoaXMgY2FsbCBoYXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggcmV3YXJkcwogICAgLy8gICBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBBU0EgdHJhbnNmZXIgZGV0YWlscwogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgY29uc3QgeGZlclR4biA9IGd0eG4uQXNzZXRUcmFuc2ZlclR4bigwKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQXNzZXRUcmFuc2ZlciwgJ1RyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcicpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0UmVjZWl2ZXIgPT09IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLCAnQXNzZXQgdHJhbnNmZXIgbXVzdCBiZSB0byBjb250cmFjdCcpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0QW1vdW50ID4gMCwgJ011c3QgcHJvdmlkZSBub24temVybyByZXdhcmRzJykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4ueGZlckFzc2V0ID09PSBhc3NldCwgJ0luY29ycmVjdCBhc3NldCBJRCcpCiAgICAvLyAKICAgIC8vICAgLy8gQWRkIHJld2FyZHMgdG8gdGhlIHBvb2wKICAgIC8vICAgdGhpcy5yZXdhcmRQb29sLnZhbHVlID0gdGhpcy5yZXdhcmRQb29sLnZhbHVlICsgeGZlclR4bi5hc3NldEFtb3VudAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIENhbGN1bGF0ZSBjdXJyZW50IEFQWSBiYXNlZCBvbiB0b3RhbCBzdGFrZWQgYW1vdW50CiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldEN1cnJlbnRBUFkoKTogdWludDY0IHsKICAgIC8vICAgY29uc3QgdG90YWxTdGFrZWQgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlCiAgICAvLyAKICAgIC8vICAgaWYgKHRvdGFsU3Rha2VkID09PSAwKSB7CiAgICAvLyAgICAgcmV0dXJuIDAgLy8gUmV0dXJuIDAgaWYgbm8gdG9rZW5zIHN0YWtlZAogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gQ2FsY3VsYXRlIGFubnVhbCByZXdhcmRzOiA1MiB3ZWVrcyAqIHdlZWtseVJld2FyZHMKICAgIC8vICAgY29uc3QgYW5udWFsUmV3YXJkczogdWludDY0ID0gNTIgKiB0aGlzLndlZWtseVJld2FyZHMudmFsdWUKICAgIC8vIAogICAgLy8gICAvLyBBUFkgPSAoYW5udWFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkKSAqIDEwMDAwIChpbiBiYXNpcyBwb2ludHMpCiAgICAvLyAgIGNvbnN0IGFweTogdWludDY0ID0gKGFubnVhbFJld2FyZHMgKiAxMDApIC8gdG90YWxTdGFrZWQKICAgIC8vIAogICAgLy8gICByZXR1cm4gYXB5CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IHBlbmRpbmcgcmV3YXJkcyBmb3IgYSBzcGVjaWZpYyB1c2VyCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldFBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogdWludDY0IHsKICAgIC8vICAgcmV0dXJuIHRoaXMuY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3MpCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogVHJpZ2dlciByZXdhcmQgZGlzdHJpYnV0aW9uIG1hbnVhbGx5IChhZG1pbiBvbmx5KQogICAgLy8gICogVXBkYXRlcyBhY2N1bXVsYXRlZCByZXdhcmRzIHBlciBzaGFyZSBpZiBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICogYW5kIGNvbXBvdW5kcyByZXdhcmRzIGZvciBhbGwgc3Rha2VycwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB0cmlnZ2VyUmV3YXJkRGlzdHJpYnV0aW9uKCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSBhZG1pbiBjYW4gdHJpZ2dlciBkaXN0cmlidXRpb24KICAgIC8vICAgY29uc3QgYWRtaW5BZGRyID0gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUKICAgIC8vICAgYXNzZXJ0KFR4bi5zZW5kZXIgPT09IGFkbWluQWRkciwgJ09ubHkgYWRtaW4gY2FuIHRyaWdnZXIgZGlzdHJpYnV0aW9uJykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgcmV3YXJkcwogICAgLy8gICB0aGlzLnVwZGF0ZVJld2FyZHMoKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCBhbGwgc3Rha2VycyBhbmQgY29tcG91bmQgdGhlaXIgcmV3YXJkcwogICAgLy8gICAvLyBOb3RlOiBJbiBBbGdvcmFuZCwgd2UgY2FuJ3QgaXRlcmF0ZSBvdmVyIGFsbCBib3hlcyBkaXJlY3RseQogICAgLy8gICAvLyBJbnN0ZWFkLCB3ZSdsbCByZWx5IG9uIHRoZSBmYWN0IHRoYXQgcmV3YXJkcyBhcmUgYXV0b21hdGljYWxseQogICAgLy8gICAvLyBjb21wb3VuZGVkIHdoZW4gdXNlcnMgaW50ZXJhY3Qgd2l0aCB0aGUgY29udHJhY3QgKHN0YWtlL3dpdGhkcmF3KQogICAgLy8gICAvLyBUaGlzIGlzIG1vcmUgZ2FzIGVmZmljaWVudCBhbmQgZm9sbG93cyBBbGdvcmFuZCdzIGRlc2lnbiBwYXR0ZXJucwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFVwZGF0ZSB0aGUgYWRtaW4gYWRkcmVzcwogICAgLy8gICogT25seSB0aGUgY3VycmVudCBhZG1pbiBjYW4gY2FsbCB0aGlzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHVwZGF0ZUFkbWluKG5ld0FkbWluQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiB1cGRhdGUgYWRtaW4nKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBhZG1pbiBhZGRyZXNzCiAgICAvLyAgIHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlID0gbmV3QWRtaW5BZGRyZXNzCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IGN1cnJlbnQgc3Rha2luZyBzdGF0aXN0aWNzIGZvciBhIHVzZXIKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCh7IHJlYWRvbmx5OiB0cnVlIH0pCiAgICAvLyBwdWJsaWMgZ2V0VXNlclN0YXRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogQXJyYXk8dWludDY0PiB7CiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcykKICAgIC8vICAgY29uc3QgcGVuZGluZ1Jld2FyZHMgPSB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHJlc3VsdDogdWludDY0W10gPSBbCiAgICAvLyAgICAgc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vICAgICBzdGFrZUluZm8ubGFzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUsCiAgICAvLyAgICAgcGVuZGluZ1Jld2FyZHMsCiAgICAvLyAgICAgc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcy5uYXRpdmUsCiAgICAvLyAgIF0KICAgIC8vIAogICAgLy8gICByZXR1cm4gcmVzdWx0CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IGNvbnRyYWN0IGdsb2JhbCBzdGF0aXN0aWNzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldENvbnRyYWN0U3RhdHMoKTogQXJyYXk8dWludDY0PiB7CiAgICAvLyAgIGNvbnN0IGN1cnJlbnRBUFkgPSB0aGlzLmdldEN1cnJlbnRBUFkoKQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHJlc3VsdDogdWludDY0W10gPSBbCiAgICAvLyAgICAgdGhpcy5hc3NldC52YWx1ZS5pZCwKICAgIC8vICAgICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlLAogICAgLy8gICAgIGN1cnJlbnRBUFksCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDM2CiAgICAvLyBjdXJyZW50QVBZLAogICAgdW5jb3ZlciA2CiAgICBpdG9iCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU2LTQzNgogICAgLy8gcHVibGljIHRvdGFsU3Rha2VkID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIGxhc3RSZXdhcmRUaW1lID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIG1pbmltdW1TdGFrZSA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIHB1YmxpYyByZXdhcmRQb29sID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIGFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gCiAgICAvLyAvLyBDb25zdGFudHMgZm9yIGZpeGVkIHJld2FyZCBzeXN0ZW0gLSBub3cgYXMgR2xvYmFsU3RhdGUgZm9yIGZsZXhpYmlsaXR5CiAgICAvLyBwdWJsaWMgd2Vla2x5UmV3YXJkcyA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIHB1YmxpYyByZXdhcmRQZXJpb2QgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyAKICAgIC8vIHB1YmxpYyBzdGFrZXJzID0gQm94TWFwPEFjY291bnQsIFVzZXJTdGFrZUluZm8+KHsga2V5UHJlZml4OiAnc3Rha2VycycgfSkKICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcmVhZCB1c2VyIHN0YWtlIGluZm8gZnJvbSBib3ggc3RvcmFnZQogICAgLy8gICovCiAgICAvLyBwdWJsaWMgZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCk6IFVzZXJTdGFrZUluZm8gewogICAgLy8gICBjb25zdCB1c2VyQm94ID0gdGhpcy5zdGFrZXJzKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGlmICh1c2VyQm94LmV4aXN0cykgewogICAgLy8gICAgIHJldHVybiB1c2VyQm94LnZhbHVlLmNvcHkoKQogICAgLy8gICB9IGVsc2UgewogICAgLy8gICAgIHJldHVybiBuZXcgVXNlclN0YWtlSW5mbyh7CiAgICAvLyAgICAgICBzdGFrZWRBbW91bnQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICBmaXJzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIGxhc3RTdGFrZVRpbWU6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICB0b3RhbFJld2FyZHNFYXJuZWQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICByZXdhcmREZWJ0OiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICAgICAgcGVuZGluZ1Jld2FyZHM6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgfSkKICAgIC8vICAgfQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byBzdG9yZSB1c2VyIHN0YWtlIGluZm8gaW4gYm94IHN0b3JhZ2UKICAgIC8vICAqLwogICAgLy8gcHVibGljIHN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCwgc3Rha2VJbmZvOiBVc2VyU3Rha2VJbmZvKTogdm9pZCB7CiAgICAvLyAgIHRoaXMuc3Rha2Vycyh1c2VyQWRkcmVzcykudmFsdWUgPSBzdGFrZUluZm8uY29weSgpCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogVXBkYXRlIGFjY3VtdWxhdGVkIHJld2FyZHMgcGVyIHNoYXJlIGlmIHJld2FyZCBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICovCiAgICAvLyBwcml2YXRlIHVwZGF0ZVJld2FyZHMoKTogdm9pZCB7CiAgICAvLyAgIGNvbnN0IGN1cnJlbnRUaW1lID0gR2xvYmFsLmxhdGVzdFRpbWVzdGFtcAogICAgLy8gICBjb25zdCBsYXN0UmV3YXJkID0gdGhpcy5sYXN0UmV3YXJkVGltZS52YWx1ZQogICAgLy8gICBjb25zdCByZXdhcmRQZXJpb2QgPSB0aGlzLnJld2FyZFBlcmlvZC52YWx1ZQogICAgLy8gCiAgICAvLyAgIC8vIENoZWNrIGlmIGEgZnVsbCByZXdhcmQgcGVyaW9kIGhhcyBwYXNzZWQKICAgIC8vICAgaWYgKGN1cnJlbnRUaW1lID49IGxhc3RSZXdhcmQgKyByZXdhcmRQZXJpb2QgJiYgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSA+IDApIHsKICAgIC8vICAgICAvLyBDYWxjdWxhdGUgaG93IG1hbnkgY29tcGxldGUgcGVyaW9kcyBoYXZlIHBhc3NlZAogICAgLy8gICAgIGNvbnN0IHBlcmlvZHNQYXNzZWQ6IHVpbnQ2NCA9IChjdXJyZW50VGltZSAtIGxhc3RSZXdhcmQpIC8gcmV3YXJkUGVyaW9kCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUKICAgIC8vICAgICBjb25zdCByZXdhcmRQZXJQZXJpb2QgPSB0aGlzLndlZWtseVJld2FyZHMudmFsdWUKICAgIC8vICAgICBjb25zdCB0b3RhbFJld2FyZHM6IHVpbnQ2NCA9IHJld2FyZFBlclBlcmlvZCAqIHBlcmlvZHNQYXNzZWQKICAgIC8vIAogICAgLy8gICAgIC8vIFNpbXBsZSBkaXZpc2lvbiAtIHJld2FyZHMgcGVyIHRva2VuIHN0YWtlZAogICAgLy8gICAgIGNvbnN0IHRvdGFsU3Rha2VkID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZQogICAgLy8gICAgIGNvbnN0IHJld2FyZFBlclNoYXJlOiB1aW50NjQgPSB0b3RhbFJld2FyZHMgLyB0b3RhbFN0YWtlZAogICAgLy8gCiAgICAvLyAgICAgLy8gVXBkYXRlIGFjY3VtdWxhdGVkIHJld2FyZHMgcGVyIHNoYXJlCiAgICAvLyAgICAgdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSA9IHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUgKyByZXdhcmRQZXJTaGFyZQogICAgLy8gCiAgICAvLyAgICAgLy8gVXBkYXRlIGxhc3QgcmV3YXJkIHRpbWUgdG8gdGhlIG1vc3QgcmVjZW50IGNvbXBsZXRlIHBlcmlvZAogICAgLy8gICAgIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBsYXN0UmV3YXJkICsgKHBlcmlvZHNQYXNzZWQgKiByZXdhcmRQZXJpb2QpCiAgICAvLyAKICAgIC8vICAgICAvLyBEZWR1Y3QgcmV3YXJkcyBmcm9tIHBvb2wKICAgIC8vICAgICB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSB0aGlzLnJld2FyZFBvb2wudmFsdWUgLSB0b3RhbFJld2FyZHMKICAgIC8vICAgfQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIENhbGN1bGF0ZSBwZW5kaW5nIHJld2FyZHMgZm9yIGEgdXNlcgogICAgLy8gICovCiAgICAvLyBwcml2YXRlIGNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogdWludDY0IHsKICAgIC8vICAgY29uc3Qgc3Rha2VJbmZvID0gdGhpcy5nZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA9PT0gMCkgewogICAgLy8gICAgIHJldHVybiAwCiAgICAvLyAgIH0KICAgIC8vIAogICAgLy8gICBjb25zdCB1c2VyU3Rha2UgPSBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZQogICAgLy8gICBjb25zdCBhY2NSZXdhcmRzUGVyU2hhcmUgPSB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlCiAgICAvLyAgIGNvbnN0IHVzZXJSZXdhcmREZWJ0ID0gc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlCiAgICAvLyAKICAgIC8vICAgLy8gU2ltcGxlIGNhbGN1bGF0aW9uIHdpdGhvdXQgcHJlY2lzaW9uCiAgICAvLyAgIGNvbnN0IHRvdGFsRWFybmVkOiB1aW50NjQgPSB1c2VyU3Rha2UgKiBhY2NSZXdhcmRzUGVyU2hhcmUKICAgIC8vICAgY29uc3QgcGVuZGluZ1Jld2FyZHM6IHVpbnQ2NCA9IHRvdGFsRWFybmVkID4gdXNlclJld2FyZERlYnQgPyB0b3RhbEVhcm5lZCAtIHVzZXJSZXdhcmREZWJ0IDogMAogICAgLy8gCiAgICAvLyAgIHJldHVybiBwZW5kaW5nUmV3YXJkcwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byBjb21wb3VuZCByZXdhcmRzIGZvciBhIHVzZXIKICAgIC8vICAqLwogICAgLy8gcHJpdmF0ZSBjb21wb3VuZFJld2FyZHModXNlckFkZHJlc3M6IEFjY291bnQpOiB2b2lkIHsKICAgIC8vICAgY29uc3Qgc3Rha2VJbmZvID0gdGhpcy5nZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzKQogICAgLy8gICBpZiAoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPiAwKSB7CiAgICAvLyAgICAgY29uc3QgcGVuZGluZ1Jld2FyZHMgPSB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gICAgIGlmIChwZW5kaW5nUmV3YXJkcyA+IDApIHsKICAgIC8vICAgICAgIC8vIEFkZCByZXdhcmRzIHRvIHN0YWtlCiAgICAvLyAgICAgICBzdGFrZUluZm8uc3Rha2VkQW1vdW50ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSArIHBlbmRpbmdSZXdhcmRzKQogICAgLy8gICAgICAgc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUgKyBwZW5kaW5nUmV3YXJkcykKICAgIC8vICAgICAgIHN0YWtlSW5mby5yZXdhcmREZWJ0ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAqIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUpCiAgICAvLyAgICAgICBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMgPSBuZXcgYXJjNC5VaW50TjY0KDApCiAgICAvLyAgICAgICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcywgc3Rha2VJbmZvKQogICAgLy8gCiAgICAvLyAgICAgICAvLyBVcGRhdGUgdG90YWwgc3Rha2VkCiAgICAvLyAgICAgICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHBlbmRpbmdSZXdhcmRzCiAgICAvLyAgICAgfQogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSW5pdGlhbGl6ZSB0aGUgY29udHJhY3Qgd2l0aCB0aGUgQVNBIHRva2VuIElEIGFuZCBvdGhlciBwYXJhbWV0ZXJzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIGluaXRpYWxpemUoCiAgICAvLyAgIGFzc2V0OiBBc3NldCwKICAgIC8vICAgYWRtaW5BZGRyZXNzOiBBY2NvdW50LAogICAgLy8gICBtaW5pbXVtU3Rha2U6IHVpbnQ2NCwKICAgIC8vICAgd2Vla2x5UmV3YXJkczogdWludDY0LAogICAgLy8gICByZXdhcmRQZXJpb2Q6IHVpbnQ2NCwKICAgIC8vICk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgdGhpcyBpcyBvbmx5IGNhbGxlZCBkdXJpbmcgY29udHJhY3QgY3JlYXRpb24KICAgIC8vICAgYXNzZXJ0KHRoaXMuYXNzZXQudmFsdWUgPT09IEFzc2V0KCksICdBbHJlYWR5IGluaXRpYWxpemVkJykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgb25seSB0aGUgY3JlYXRvciBjYW4gaW5pdGlhbGl6ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gR2xvYmFsLmNyZWF0b3JBZGRyZXNzLCAnT25seSBjcmVhdG9yIGNhbiBpbml0aWFsaXplJykKICAgIC8vIAogICAgLy8gICAvLyBTdG9yZSB0aGUgaW5pdGlhbCBwYXJhbWV0ZXJzCiAgICAvLyAgIHRoaXMuYXNzZXQudmFsdWUgPSBhc3NldAogICAgLy8gICB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZSA9IGFkbWluQWRkcmVzcwogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gMAogICAgLy8gICB0aGlzLmxhc3RSZXdhcmRUaW1lLnZhbHVlID0gR2xvYmFsLmxhdGVzdFRpbWVzdGFtcAogICAgLy8gICB0aGlzLm1pbmltdW1TdGFrZS52YWx1ZSA9IG1pbmltdW1TdGFrZQogICAgLy8gICB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSAwCiAgICAvLyAgIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUgPSAwCiAgICAvLyAKICAgIC8vICAgLy8gU2V0IHJld2FyZCBzeXN0ZW0gcGFyYW1ldGVycwogICAgLy8gICB0aGlzLndlZWtseVJld2FyZHMudmFsdWUgPSB3ZWVrbHlSZXdhcmRzCiAgICAvLyAgIHRoaXMucmV3YXJkUGVyaW9kLnZhbHVlID0gcmV3YXJkUGVyaW9kCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogT3B0IHRoZSBjb250cmFjdCBpbnRvIHRoZSBBU0EKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgb3B0SW5Ub0Fzc2V0KCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSB0aGUgY3JlYXRvciBvciBhZG1pbiBjYW4gb3B0IGluCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBHbG9iYWwuY3JlYXRvckFkZHJlc3MgfHwgVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBjcmVhdG9yIG9yIGFkbWluIGNhbiBvcHQgaW4nKQogICAgLy8gCiAgICAvLyAgIC8vIE9wdCB0aGUgY29udHJhY3QgaW50byB0aGUgQVNBCiAgICAvLyAgIGNvbnN0IGFzc2V0ID0gdGhpcy5hc3NldC52YWx1ZQogICAgLy8gICBpdHhuCiAgICAvLyAgICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgICAgYXNzZXRSZWNlaXZlcjogR2xvYmFsLmN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MsCiAgICAvLyAgICAgICBhc3NldEFtb3VudDogMCwKICAgIC8vICAgICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgICAgfSkKICAgIC8vICAgICAuc3VibWl0KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBTdGFrZSB0b2tlbnMKICAgIC8vICAqIFJlcXVpcmVzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbgogICAgLy8gICogQXV0b21hdGljYWxseSBjbGFpbXMgcGVuZGluZyByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHN0YWtlKCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgdGhlIGNvbnRyYWN0IGhhcyBvcHRlZCBpbnRvIHRoZSBBU0EKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGFzc2VydCh0aGlzLmFzc2V0LnZhbHVlICE9PSBBc3NldCgpLCAnQ29udHJhY3Qgbm90IGluaXRpYWxpemVkJykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgdGhpcyBjYWxsIGhhcyBhIGNvbXBhbmlvbiBBU0EgdHJhbnNmZXIgdHJhbnNhY3Rpb24KICAgIC8vICAgYXNzZXJ0KEdsb2JhbC5ncm91cFNpemUgPT09IDIsICdFeHBlY3RlZCAyIHR4bnMgaW4gZ3JvdXAnKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCB0aGUgQVNBIHRyYW5zZmVyIGRldGFpbHMKICAgIC8vICAgY29uc3QgeGZlclR4biA9IGd0eG4uQXNzZXRUcmFuc2ZlclR4bigwKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQXNzZXRUcmFuc2ZlciwgJ1RyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcicpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0UmVjZWl2ZXIgPT09IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLCAnQXNzZXQgdHJhbnNmZXIgbXVzdCBiZSB0byBjb250cmFjdCcpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0QW1vdW50ID4gMCwgJ011c3Qgc3Rha2Ugbm9uLXplcm8gYW1vdW50JykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4ueGZlckFzc2V0ID09PSBhc3NldCwgJ0luY29ycmVjdCBhc3NldCBJRCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBzdGFrZSBhbW91bnQgZnJvbSB0aGUgdHJhbnNhY3Rpb24KICAgIC8vICAgY29uc3Qgc3Rha2VBbW91bnQgPSB4ZmVyVHhuLmFzc2V0QW1vdW50CiAgICAvLyAgIGNvbnN0IG1pbmltdW1TdGFrZSA9IHRoaXMubWluaW11bVN0YWtlLnZhbHVlCiAgICAvLyAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBUeG4uc2VuZGVyCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBjdXJyZW50IHVzZXIgc3Rha2UgaW5mbwogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICAvLyBJZiB0aGlzIGlzIGEgbmV3IHN0YWtlLCBlbnN1cmUgaXQgbWVldHMgbWluaW11bQogICAgLy8gICBpZiAoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPT09IDApIHsKICAgIC8vICAgICBhc3NlcnQoc3Rha2VBbW91bnQgPj0gbWluaW11bVN0YWtlLCAnSW5pdGlhbCBzdGFrZSBiZWxvdyBtaW5pbXVtJykKICAgIC8vICAgICAvLyBTZXQgdGhlIGZpcnN0IHN0YWtlIHRpbWUgKHRoaXMgbmV2ZXIgY2hhbmdlcyBhZnRlciBpbml0aWFsIHN0YWtlKQogICAgLy8gICAgIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZSA9IG5ldyBhcmM0LlVpbnRONjQoR2xvYmFsLmxhdGVzdFRpbWVzdGFtcCkKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBzdGFrZSBpbmZvIHdpdGggbmV3IGFtb3VudAogICAgLy8gICBzdGFrZUluZm8uc3Rha2VkQW1vdW50ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSArIHN0YWtlQW1vdW50KQogICAgLy8gICBzdGFrZUluZm8ubGFzdFN0YWtlVGltZSA9IG5ldyBhcmM0LlVpbnRONjQoR2xvYmFsLmxhdGVzdFRpbWVzdGFtcCkKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgcmV3YXJkIGRlYnQKICAgIC8vICAgc3Rha2VJbmZvLnJld2FyZERlYnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICogdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSkKICAgIC8vIAogICAgLy8gICAvLyBTdG9yZSB1cGRhdGVkIHN0YWtlIGluZm8KICAgIC8vICAgdGhpcy5zdG9yZVVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcywgc3Rha2VJbmZvKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBnbG9iYWwgc3RhdGUKICAgIC8vICAgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSA9IHRoaXMudG90YWxTdGFrZWQudmFsdWUgKyBzdGFrZUFtb3VudAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFdpdGhkcmF3IHN0YWtlZCB0b2tlbnMKICAgIC8vICAqIEF1dG9tYXRpY2FsbHkgY2xhaW1zIHBlbmRpbmcgcmV3YXJkcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB3aXRoZHJhdyhhbW91bnQ6IHVpbnQ2NCk6IHZvaWQgewogICAgLy8gICBjb25zdCBzZW5kZXJBZGRyZXNzID0gVHhuLnNlbmRlcgogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgdXNlciBoYXMgZW5vdWdoIHN0YWtlZAogICAgLy8gICBhc3NlcnQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPiAwLCAnTm8gc3Rha2UgZm91bmQnKQogICAgLy8gICBhc3NlcnQoYW1vdW50IDw9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLCAnV2l0aGRyYXdhbCBhbW91bnQgZXhjZWVkcyBzdGFrZScpCiAgICAvLyAgIGFzc2VydChhbW91bnQgPiAwLCAnV2l0aGRyYXdhbCBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZScpCiAgICAvLyAKICAgIC8vICAgLy8gSWYgd2l0aGRyYXdpbmcgYWxsLCBubyBuZWVkIHRvIGNoZWNrIG1pbmltdW0gcmVtYWluaW5nCiAgICAvLyAgIC8vIElmIHBhcnRpYWwgd2l0aGRyYXdhbCwgZW5zdXJlIHJlbWFpbmluZyBzdGFrZSBtZWV0cyBtaW5pbXVtCiAgICAvLyAgIGlmIChhbW91bnQgPCBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSkgewogICAgLy8gICAgIGNvbnN0IHJlbWFpbmluZ1N0YWtlOiB1aW50NjQgPSBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAtIGFtb3VudAogICAgLy8gICAgIGNvbnN0IG1pbmltdW1TdGFrZSA9IHRoaXMubWluaW11bVN0YWtlLnZhbHVlCiAgICAvLyAgICAgYXNzZXJ0KHJlbWFpbmluZ1N0YWtlID49IG1pbmltdW1TdGFrZSwgJ1JlbWFpbmluZyBzdGFrZSB3b3VsZCBiZSBiZWxvdyBtaW5pbXVtJykKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBzdGFrZSBpbmZvCiAgICAvLyAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlIC0gYW1vdW50KQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSByZXdhcmQgZGVidAogICAgLy8gICBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHVwZGF0ZWQgc3Rha2UgaW5mbwogICAgLy8gICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIGdsb2JhbCBzdGF0ZQogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSAtIGFtb3VudAogICAgLy8gCiAgICAvLyAgIC8vIFRyYW5zZmVyIHRva2VucyBiYWNrIHRvIHVzZXIKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGl0eG4KICAgIC8vICAgICAuYXNzZXRUcmFuc2Zlcih7CiAgICAvLyAgICAgICBhc3NldFJlY2VpdmVyOiBzZW5kZXJBZGRyZXNzLAogICAgLy8gICAgICAgYXNzZXRBbW91bnQ6IGFtb3VudCwKICAgIC8vICAgICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgICAgICBmZWU6IDEwMDAsCiAgICAvLyAgICAgfSkKICAgIC8vICAgICAuc3VibWl0KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBBZGQgcmV3YXJkcyB0byB0aGUgcmV3YXJkIHBvb2wKICAgIC8vICAqIE9ubHkgdGhlIGFkbWluIGNhbiBjYWxsIHRoaXMKICAgIC8vICAqIFJlcXVpcmVzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aXRoIHRoZSByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIGFkZFJld2FyZHMoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IGFkbWluIGNhbiBhZGQgcmV3YXJkcwogICAgLy8gICBjb25zdCBhZG1pbkFkZHIgPSB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBhZG1pbiBjYW4gYWRkIHJld2FyZHMnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGNhbGwgaGFzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aXRoIHJld2FyZHMKICAgIC8vICAgYXNzZXJ0KEdsb2JhbC5ncm91cFNpemUgPT09IDIsICdFeHBlY3RlZCAyIHR4bnMgaW4gZ3JvdXAnKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCB0aGUgQVNBIHRyYW5zZmVyIGRldGFpbHMKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGNvbnN0IHhmZXJUeG4gPSBndHhuLkFzc2V0VHJhbnNmZXJUeG4oMCkKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkFzc2V0VHJhbnNmZXIsICdUcmFuc2FjdGlvbiAwIG11c3QgYmUgYXNzZXQgdHJhbnNmZXInKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi5hc3NldFJlY2VpdmVyID09PSBHbG9iYWwuY3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcywgJ0Fzc2V0IHRyYW5zZmVyIG11c3QgYmUgdG8gY29udHJhY3QnKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi5hc3NldEFtb3VudCA+IDAsICdNdXN0IHByb3ZpZGUgbm9uLXplcm8gcmV3YXJkcycpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLnhmZXJBc3NldCA9PT0gYXNzZXQsICdJbmNvcnJlY3QgYXNzZXQgSUQnKQogICAgLy8gCiAgICAvLyAgIC8vIEFkZCByZXdhcmRzIHRvIHRoZSBwb29sCiAgICAvLyAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IHRoaXMucmV3YXJkUG9vbC52YWx1ZSArIHhmZXJUeG4uYXNzZXRBbW91bnQKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBDYWxjdWxhdGUgY3VycmVudCBBUFkgYmFzZWQgb24gdG90YWwgc3Rha2VkIGFtb3VudAogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRDdXJyZW50QVBZKCk6IHVpbnQ2NCB7CiAgICAvLyAgIGNvbnN0IHRvdGFsU3Rha2VkID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZQogICAgLy8gCiAgICAvLyAgIGlmICh0b3RhbFN0YWtlZCA9PT0gMCkgewogICAgLy8gICAgIHJldHVybiAwIC8vIFJldHVybiAwIGlmIG5vIHRva2VucyBzdGFrZWQKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIENhbGN1bGF0ZSBhbm51YWwgcmV3YXJkczogNTIgd2Vla3MgKiB3ZWVrbHlSZXdhcmRzCiAgICAvLyAgIGNvbnN0IGFubnVhbFJld2FyZHM6IHVpbnQ2NCA9IDUyICogdGhpcy53ZWVrbHlSZXdhcmRzLnZhbHVlCiAgICAvLyAKICAgIC8vICAgLy8gQVBZID0gKGFubnVhbFJld2FyZHMgLyB0b3RhbFN0YWtlZCkgKiAxMDAwMCAoaW4gYmFzaXMgcG9pbnRzKQogICAgLy8gICBjb25zdCBhcHk6IHVpbnQ2NCA9IChhbm51YWxSZXdhcmRzICogMTAwKSAvIHRvdGFsU3Rha2VkCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIGFweQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBwZW5kaW5nIHJld2FyZHMgZm9yIGEgc3BlY2lmaWMgdXNlcgogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHVpbnQ2NCB7CiAgICAvLyAgIHJldHVybiB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFRyaWdnZXIgcmV3YXJkIGRpc3RyaWJ1dGlvbiBtYW51YWxseSAoYWRtaW4gb25seSkKICAgIC8vICAqIFVwZGF0ZXMgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUgaWYgcGVyaW9kIGhhcyBwYXNzZWQKICAgIC8vICAqIGFuZCBjb21wb3VuZHMgcmV3YXJkcyBmb3IgYWxsIHN0YWtlcnMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgdHJpZ2dlclJld2FyZERpc3RyaWJ1dGlvbigpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIHRyaWdnZXIgZGlzdHJpYnV0aW9uCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiB0cmlnZ2VyIGRpc3RyaWJ1dGlvbicpCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHJld2FyZHMKICAgIC8vICAgdGhpcy51cGRhdGVSZXdhcmRzKCkKICAgIC8vIAogICAgLy8gICAvLyBHZXQgYWxsIHN0YWtlcnMgYW5kIGNvbXBvdW5kIHRoZWlyIHJld2FyZHMKICAgIC8vICAgLy8gTm90ZTogSW4gQWxnb3JhbmQsIHdlIGNhbid0IGl0ZXJhdGUgb3ZlciBhbGwgYm94ZXMgZGlyZWN0bHkKICAgIC8vICAgLy8gSW5zdGVhZCwgd2UnbGwgcmVseSBvbiB0aGUgZmFjdCB0aGF0IHJld2FyZHMgYXJlIGF1dG9tYXRpY2FsbHkKICAgIC8vICAgLy8gY29tcG91bmRlZCB3aGVuIHVzZXJzIGludGVyYWN0IHdpdGggdGhlIGNvbnRyYWN0IChzdGFrZS93aXRoZHJhdykKICAgIC8vICAgLy8gVGhpcyBpcyBtb3JlIGdhcyBlZmZpY2llbnQgYW5kIGZvbGxvd3MgQWxnb3JhbmQncyBkZXNpZ24gcGF0dGVybnMKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBVcGRhdGUgdGhlIGFkbWluIGFkZHJlc3MKICAgIC8vICAqIE9ubHkgdGhlIGN1cnJlbnQgYWRtaW4gY2FuIGNhbGwgdGhpcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB1cGRhdGVBZG1pbihuZXdBZG1pbkFkZHJlc3M6IEFjY291bnQpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIHVwZGF0ZSBhZG1pbgogICAgLy8gICBjb25zdCBhZG1pbkFkZHIgPSB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluJykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgYWRtaW4gYWRkcmVzcwogICAgLy8gICB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZSA9IG5ld0FkbWluQWRkcmVzcwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBjdXJyZW50IHN0YWtpbmcgc3RhdGlzdGljcyBmb3IgYSB1c2VyCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldFVzZXJTdGF0cyh1c2VyQWRkcmVzczogQWNjb3VudCk6IEFycmF5PHVpbnQ2ND4gewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAgIGNvbnN0IHBlbmRpbmdSZXdhcmRzID0gdGhpcy5jYWxjdWxhdGVQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICBjb25zdCByZXN1bHQ6IHVpbnQ2NFtdID0gWwogICAgLy8gICAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLmxhc3RTdGFrZVRpbWUubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby50b3RhbFJld2FyZHNFYXJuZWQubmF0aXZlLAogICAgLy8gICAgIHBlbmRpbmdSZXdhcmRzLAogICAgLy8gICAgIHN0YWtlSW5mby5yZXdhcmREZWJ0Lm5hdGl2ZSwKICAgIC8vICAgICBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMubmF0aXZlLAogICAgLy8gICBdCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIHJlc3VsdAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBjb250cmFjdCBnbG9iYWwgc3RhdGlzdGljcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRDb250cmFjdFN0YXRzKCk6IEFycmF5PHVpbnQ2ND4gewogICAgLy8gICBjb25zdCBjdXJyZW50QVBZID0gdGhpcy5nZXRDdXJyZW50QVBZKCkKICAgIC8vIAogICAgLy8gICBjb25zdCByZXN1bHQ6IHVpbnQ2NFtdID0gWwogICAgLy8gICAgIHRoaXMuYXNzZXQudmFsdWUuaWQsCiAgICAvLyAgICAgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSwKICAgIC8vICAgICBjdXJyZW50QVBZLAogICAgY29uY2F0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU3CiAgICAvLyBwdWJsaWMgbGFzdFJld2FyZFRpbWUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICB1bmNvdmVyIDUKICAgIGl0b2IKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYtNDM2CiAgICAvLyBwdWJsaWMgdG90YWxTdGFrZWQgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgbGFzdFJld2FyZFRpbWUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgbWluaW11bVN0YWtlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIHJld2FyZFBvb2wgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyAKICAgIC8vIC8vIENvbnN0YW50cyBmb3IgZml4ZWQgcmV3YXJkIHN5c3RlbSAtIG5vdyBhcyBHbG9iYWxTdGF0ZSBmb3IgZmxleGliaWxpdHkKICAgIC8vIHB1YmxpYyB3ZWVrbHlSZXdhcmRzID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIHJld2FyZFBlcmlvZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIAogICAgLy8gcHVibGljIHN0YWtlcnMgPSBCb3hNYXA8QWNjb3VudCwgVXNlclN0YWtlSW5mbz4oeyBrZXlQcmVmaXg6ICdzdGFrZXJzJyB9KQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byByZWFkIHVzZXIgc3Rha2UgaW5mbyBmcm9tIGJveCBzdG9yYWdlCiAgICAvLyAgKi8KICAgIC8vIHB1YmxpYyBnZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogVXNlclN0YWtlSW5mbyB7CiAgICAvLyAgIGNvbnN0IHVzZXJCb3ggPSB0aGlzLnN0YWtlcnModXNlckFkZHJlc3MpCiAgICAvLyAKICAgIC8vICAgaWYgKHVzZXJCb3guZXhpc3RzKSB7CiAgICAvLyAgICAgcmV0dXJuIHVzZXJCb3gudmFsdWUuY29weSgpCiAgICAvLyAgIH0gZWxzZSB7CiAgICAvLyAgICAgcmV0dXJuIG5ldyBVc2VyU3Rha2VJbmZvKHsKICAgIC8vICAgICAgIHN0YWtlZEFtb3VudDogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIGZpcnN0U3Rha2VUaW1lOiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICAgICAgbGFzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIHRvdGFsUmV3YXJkc0Vhcm5lZDogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIHJld2FyZERlYnQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICBwZW5kaW5nUmV3YXJkczogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICB9KQogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSGVscGVyIGZ1bmN0aW9uIHRvIHN0b3JlIHVzZXIgc3Rha2UgaW5mbyBpbiBib3ggc3RvcmFnZQogICAgLy8gICovCiAgICAvLyBwdWJsaWMgc3RvcmVVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50LCBzdGFrZUluZm86IFVzZXJTdGFrZUluZm8pOiB2b2lkIHsKICAgIC8vICAgdGhpcy5zdGFrZXJzKHVzZXJBZGRyZXNzKS52YWx1ZSA9IHN0YWtlSW5mby5jb3B5KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUgaWYgcmV3YXJkIHBlcmlvZCBoYXMgcGFzc2VkCiAgICAvLyAgKi8KICAgIC8vIHByaXZhdGUgdXBkYXRlUmV3YXJkcygpOiB2b2lkIHsKICAgIC8vICAgY29uc3QgY3VycmVudFRpbWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICAvLyAgIGNvbnN0IGxhc3RSZXdhcmQgPSB0aGlzLmxhc3RSZXdhcmRUaW1lLnZhbHVlCiAgICAvLyAgIGNvbnN0IHJld2FyZFBlcmlvZCA9IHRoaXMucmV3YXJkUGVyaW9kLnZhbHVlCiAgICAvLyAKICAgIC8vICAgLy8gQ2hlY2sgaWYgYSBmdWxsIHJld2FyZCBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICBpZiAoY3VycmVudFRpbWUgPj0gbGFzdFJld2FyZCArIHJld2FyZFBlcmlvZCAmJiB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID4gMCkgewogICAgLy8gICAgIC8vIENhbGN1bGF0ZSBob3cgbWFueSBjb21wbGV0ZSBwZXJpb2RzIGhhdmUgcGFzc2VkCiAgICAvLyAgICAgY29uc3QgcGVyaW9kc1Bhc3NlZDogdWludDY0ID0gKGN1cnJlbnRUaW1lIC0gbGFzdFJld2FyZCkgLyByZXdhcmRQZXJpb2QKICAgIC8vIAogICAgLy8gICAgIC8vIFVwZGF0ZSBhY2N1bXVsYXRlZCByZXdhcmRzIHBlciBzaGFyZQogICAgLy8gICAgIGNvbnN0IHJld2FyZFBlclBlcmlvZCA9IHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZQogICAgLy8gICAgIGNvbnN0IHRvdGFsUmV3YXJkczogdWludDY0ID0gcmV3YXJkUGVyUGVyaW9kICogcGVyaW9kc1Bhc3NlZAogICAgLy8gCiAgICAvLyAgICAgLy8gU2ltcGxlIGRpdmlzaW9uIC0gcmV3YXJkcyBwZXIgdG9rZW4gc3Rha2VkCiAgICAvLyAgICAgY29uc3QgdG90YWxTdGFrZWQgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlCiAgICAvLyAgICAgY29uc3QgcmV3YXJkUGVyU2hhcmU6IHVpbnQ2NCA9IHRvdGFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUKICAgIC8vICAgICB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlID0gdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSArIHJld2FyZFBlclNoYXJlCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgbGFzdCByZXdhcmQgdGltZSB0byB0aGUgbW9zdCByZWNlbnQgY29tcGxldGUgcGVyaW9kCiAgICAvLyAgICAgdGhpcy5sYXN0UmV3YXJkVGltZS52YWx1ZSA9IGxhc3RSZXdhcmQgKyAocGVyaW9kc1Bhc3NlZCAqIHJld2FyZFBlcmlvZCkKICAgIC8vIAogICAgLy8gICAgIC8vIERlZHVjdCByZXdhcmRzIGZyb20gcG9vbAogICAgLy8gICAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IHRoaXMucmV3YXJkUG9vbC52YWx1ZSAtIHRvdGFsUmV3YXJkcwogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogQ2FsY3VsYXRlIHBlbmRpbmcgcmV3YXJkcyBmb3IgYSB1c2VyCiAgICAvLyAgKi8KICAgIC8vIHByaXZhdGUgY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3M6IEFjY291bnQpOiB1aW50NjQgewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAKICAgIC8vICAgaWYgKHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlID09PSAwKSB7CiAgICAvLyAgICAgcmV0dXJuIDAKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHVzZXJTdGFrZSA9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlCiAgICAvLyAgIGNvbnN0IGFjY1Jld2FyZHNQZXJTaGFyZSA9IHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUKICAgIC8vICAgY29uc3QgdXNlclJld2FyZERlYnQgPSBzdGFrZUluZm8ucmV3YXJkRGVidC5uYXRpdmUKICAgIC8vIAogICAgLy8gICAvLyBTaW1wbGUgY2FsY3VsYXRpb24gd2l0aG91dCBwcmVjaXNpb24KICAgIC8vICAgY29uc3QgdG90YWxFYXJuZWQ6IHVpbnQ2NCA9IHVzZXJTdGFrZSAqIGFjY1Jld2FyZHNQZXJTaGFyZQogICAgLy8gICBjb25zdCBwZW5kaW5nUmV3YXJkczogdWludDY0ID0gdG90YWxFYXJuZWQgPiB1c2VyUmV3YXJkRGVidCA/IHRvdGFsRWFybmVkIC0gdXNlclJld2FyZERlYnQgOiAwCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIHBlbmRpbmdSZXdhcmRzCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSGVscGVyIGZ1bmN0aW9uIHRvIGNvbXBvdW5kIHJld2FyZHMgZm9yIGEgdXNlcgogICAgLy8gICovCiAgICAvLyBwcml2YXRlIGNvbXBvdW5kUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA+IDApIHsKICAgIC8vICAgICBjb25zdCBwZW5kaW5nUmV3YXJkcyA9IHRoaXMuY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3MpCiAgICAvLyAgICAgaWYgKHBlbmRpbmdSZXdhcmRzID4gMCkgewogICAgLy8gICAgICAgLy8gQWRkIHJld2FyZHMgdG8gc3Rha2UKICAgIC8vICAgICAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICsgcGVuZGluZ1Jld2FyZHMpCiAgICAvLyAgICAgICBzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkLm5hdGl2ZSArIHBlbmRpbmdSZXdhcmRzKQogICAgLy8gICAgICAgc3Rha2VJbmZvLnJld2FyZERlYnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICogdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSkKICAgIC8vICAgICAgIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcyA9IG5ldyBhcmM0LlVpbnRONjQoMCkKICAgIC8vICAgICAgIHRoaXMuc3RvcmVVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgICAgIC8vIFVwZGF0ZSB0b3RhbCBzdGFrZWQKICAgIC8vICAgICAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlICsgcGVuZGluZ1Jld2FyZHMKICAgIC8vICAgICB9CiAgICAvLyAgIH0KICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBJbml0aWFsaXplIHRoZSBjb250cmFjdCB3aXRoIHRoZSBBU0EgdG9rZW4gSUQgYW5kIG90aGVyIHBhcmFtZXRlcnMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgaW5pdGlhbGl6ZSgKICAgIC8vICAgYXNzZXQ6IEFzc2V0LAogICAgLy8gICBhZG1pbkFkZHJlc3M6IEFjY291bnQsCiAgICAvLyAgIG1pbmltdW1TdGFrZTogdWludDY0LAogICAgLy8gICB3ZWVrbHlSZXdhcmRzOiB1aW50NjQsCiAgICAvLyAgIHJld2FyZFBlcmlvZDogdWludDY0LAogICAgLy8gKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGlzIG9ubHkgY2FsbGVkIGR1cmluZyBjb250cmFjdCBjcmVhdGlvbgogICAgLy8gICBhc3NlcnQodGhpcy5hc3NldC52YWx1ZSA9PT0gQXNzZXQoKSwgJ0FscmVhZHkgaW5pdGlhbGl6ZWQnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IHRoZSBjcmVhdG9yIGNhbiBpbml0aWFsaXplCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBHbG9iYWwuY3JlYXRvckFkZHJlc3MsICdPbmx5IGNyZWF0b3IgY2FuIGluaXRpYWxpemUnKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHRoZSBpbml0aWFsIHBhcmFtZXRlcnMKICAgIC8vICAgdGhpcy5hc3NldC52YWx1ZSA9IGFzc2V0CiAgICAvLyAgIHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlID0gYWRtaW5BZGRyZXNzCiAgICAvLyAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSAwCiAgICAvLyAgIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICAvLyAgIHRoaXMubWluaW11bVN0YWtlLnZhbHVlID0gbWluaW11bVN0YWtlCiAgICAvLyAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IDAKICAgIC8vICAgdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSA9IDAKICAgIC8vIAogICAgLy8gICAvLyBTZXQgcmV3YXJkIHN5c3RlbSBwYXJhbWV0ZXJzCiAgICAvLyAgIHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZSA9IHdlZWtseVJld2FyZHMKICAgIC8vICAgdGhpcy5yZXdhcmRQZXJpb2QudmFsdWUgPSByZXdhcmRQZXJpb2QKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBPcHQgdGhlIGNvbnRyYWN0IGludG8gdGhlIEFTQQogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyBvcHRJblRvQXNzZXQoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IHRoZSBjcmVhdG9yIG9yIGFkbWluIGNhbiBvcHQgaW4KICAgIC8vICAgY29uc3QgYWRtaW5BZGRyID0gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUKICAgIC8vICAgYXNzZXJ0KFR4bi5zZW5kZXIgPT09IEdsb2JhbC5jcmVhdG9yQWRkcmVzcyB8fCBUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGNyZWF0b3Igb3IgYWRtaW4gY2FuIG9wdCBpbicpCiAgICAvLyAKICAgIC8vICAgLy8gT3B0IHRoZSBjb250cmFjdCBpbnRvIHRoZSBBU0EKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGl0eG4KICAgIC8vICAgICAuYXNzZXRUcmFuc2Zlcih7CiAgICAvLyAgICAgICBhc3NldFJlY2VpdmVyOiBHbG9iYWwuY3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcywKICAgIC8vICAgICAgIGFzc2V0QW1vdW50OiAwLAogICAgLy8gICAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICB9KQogICAgLy8gICAgIC5zdWJtaXQoKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFN0YWtlIHRva2VucwogICAgLy8gICogUmVxdWlyZXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uCiAgICAvLyAgKiBBdXRvbWF0aWNhbGx5IGNsYWltcyBwZW5kaW5nIHJld2FyZHMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgc3Rha2UoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSB0aGUgY29udHJhY3QgaGFzIG9wdGVkIGludG8gdGhlIEFTQQogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgYXNzZXJ0KHRoaXMuYXNzZXQudmFsdWUgIT09IEFzc2V0KCksICdDb250cmFjdCBub3QgaW5pdGlhbGl6ZWQnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGNhbGwgaGFzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbgogICAgLy8gICBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBBU0EgdHJhbnNmZXIgZGV0YWlscwogICAgLy8gICBjb25zdCB4ZmVyVHhuID0gZ3R4bi5Bc3NldFRyYW5zZmVyVHhuKDApCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5Bc3NldFRyYW5zZmVyLCAnVHJhbnNhY3Rpb24gMCBtdXN0IGJlIGFzc2V0IHRyYW5zZmVyJykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4uYXNzZXRSZWNlaXZlciA9PT0gR2xvYmFsLmN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MsICdBc3NldCB0cmFuc2ZlciBtdXN0IGJlIHRvIGNvbnRyYWN0JykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4uYXNzZXRBbW91bnQgPiAwLCAnTXVzdCBzdGFrZSBub24temVybyBhbW91bnQnKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi54ZmVyQXNzZXQgPT09IGFzc2V0LCAnSW5jb3JyZWN0IGFzc2V0IElEJykKICAgIC8vIAogICAgLy8gICAvLyBHZXQgdGhlIHN0YWtlIGFtb3VudCBmcm9tIHRoZSB0cmFuc2FjdGlvbgogICAgLy8gICBjb25zdCBzdGFrZUFtb3VudCA9IHhmZXJUeG4uYXNzZXRBbW91bnQKICAgIC8vICAgY29uc3QgbWluaW11bVN0YWtlID0gdGhpcy5taW5pbXVtU3Rha2UudmFsdWUKICAgIC8vICAgY29uc3Qgc2VuZGVyQWRkcmVzcyA9IFR4bi5zZW5kZXIKICAgIC8vIAogICAgLy8gICAvLyBHZXQgdGhlIGN1cnJlbnQgdXNlciBzdGFrZSBpbmZvCiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIC8vIElmIHRoaXMgaXMgYSBuZXcgc3Rha2UsIGVuc3VyZSBpdCBtZWV0cyBtaW5pbXVtCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA9PT0gMCkgewogICAgLy8gICAgIGFzc2VydChzdGFrZUFtb3VudCA+PSBtaW5pbXVtU3Rha2UsICdJbml0aWFsIHN0YWtlIGJlbG93IG1pbmltdW0nKQogICAgLy8gICAgIC8vIFNldCB0aGUgZmlyc3Qgc3Rha2UgdGltZSAodGhpcyBuZXZlciBjaGFuZ2VzIGFmdGVyIGluaXRpYWwgc3Rha2UpCiAgICAvLyAgICAgc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lID0gbmV3IGFyYzQuVWludE42NChHbG9iYWwubGF0ZXN0VGltZXN0YW1wKQogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHN0YWtlIGluZm8gd2l0aCBuZXcgYW1vdW50CiAgICAvLyAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICsgc3Rha2VBbW91bnQpCiAgICAvLyAgIHN0YWtlSW5mby5sYXN0U3Rha2VUaW1lID0gbmV3IGFyYzQuVWludE42NChHbG9iYWwubGF0ZXN0VGltZXN0YW1wKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSByZXdhcmQgZGVidAogICAgLy8gICBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHVwZGF0ZWQgc3Rha2UgaW5mbwogICAgLy8gICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIGdsb2JhbCBzdGF0ZQogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHN0YWtlQW1vdW50CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogV2l0aGRyYXcgc3Rha2VkIHRva2VucwogICAgLy8gICogQXV0b21hdGljYWxseSBjbGFpbXMgcGVuZGluZyByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHdpdGhkcmF3KGFtb3VudDogdWludDY0KTogdm9pZCB7CiAgICAvLyAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBUeG4uc2VuZGVyCiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB1c2VyIGhhcyBlbm91Z2ggc3Rha2VkCiAgICAvLyAgIGFzc2VydChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA+IDAsICdObyBzdGFrZSBmb3VuZCcpCiAgICAvLyAgIGFzc2VydChhbW91bnQgPD0gc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsICdXaXRoZHJhd2FsIGFtb3VudCBleGNlZWRzIHN0YWtlJykKICAgIC8vICAgYXNzZXJ0KGFtb3VudCA+IDAsICdXaXRoZHJhd2FsIGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlJykKICAgIC8vIAogICAgLy8gICAvLyBJZiB3aXRoZHJhd2luZyBhbGwsIG5vIG5lZWQgdG8gY2hlY2sgbWluaW11bSByZW1haW5pbmcKICAgIC8vICAgLy8gSWYgcGFydGlhbCB3aXRoZHJhd2FsLCBlbnN1cmUgcmVtYWluaW5nIHN0YWtlIG1lZXRzIG1pbmltdW0KICAgIC8vICAgaWYgKGFtb3VudCA8IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlKSB7CiAgICAvLyAgICAgY29uc3QgcmVtYWluaW5nU3Rha2U6IHVpbnQ2NCA9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlIC0gYW1vdW50CiAgICAvLyAgICAgY29uc3QgbWluaW11bVN0YWtlID0gdGhpcy5taW5pbXVtU3Rha2UudmFsdWUKICAgIC8vICAgICBhc3NlcnQocmVtYWluaW5nU3Rha2UgPj0gbWluaW11bVN0YWtlLCAnUmVtYWluaW5nIHN0YWtlIHdvdWxkIGJlIGJlbG93IG1pbmltdW0nKQogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHN0YWtlIGluZm8KICAgIC8vICAgc3Rha2VJbmZvLnN0YWtlZEFtb3VudCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgLSBhbW91bnQpCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHJld2FyZCBkZWJ0CiAgICAvLyAgIHN0YWtlSW5mby5yZXdhcmREZWJ0ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAqIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUpCiAgICAvLyAKICAgIC8vICAgLy8gU3RvcmUgdXBkYXRlZCBzdGFrZSBpbmZvCiAgICAvLyAgIHRoaXMuc3RvcmVVc2VyU3Rha2VJbmZvKHNlbmRlckFkZHJlc3MsIHN0YWtlSW5mbykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgZ2xvYmFsIHN0YXRlCiAgICAvLyAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlIC0gYW1vdW50CiAgICAvLyAKICAgIC8vICAgLy8gVHJhbnNmZXIgdG9rZW5zIGJhY2sgdG8gdXNlcgogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgaXR4bgogICAgLy8gICAgIC5hc3NldFRyYW5zZmVyKHsKICAgIC8vICAgICAgIGFzc2V0UmVjZWl2ZXI6IHNlbmRlckFkZHJlc3MsCiAgICAvLyAgICAgICBhc3NldEFtb3VudDogYW1vdW50LAogICAgLy8gICAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICAgIGZlZTogMTAwMCwKICAgIC8vICAgICB9KQogICAgLy8gICAgIC5zdWJtaXQoKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEFkZCByZXdhcmRzIHRvIHRoZSByZXdhcmQgcG9vbAogICAgLy8gICogT25seSB0aGUgYWRtaW4gY2FuIGNhbGwgdGhpcwogICAgLy8gICogUmVxdWlyZXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggdGhlIHJld2FyZHMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgYWRkUmV3YXJkcygpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIGFkZCByZXdhcmRzCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiBhZGQgcmV3YXJkcycpCiAgICAvLyAKICAgIC8vICAgLy8gRW5zdXJlIHRoaXMgY2FsbCBoYXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggcmV3YXJkcwogICAgLy8gICBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBBU0EgdHJhbnNmZXIgZGV0YWlscwogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgY29uc3QgeGZlclR4biA9IGd0eG4uQXNzZXRUcmFuc2ZlclR4bigwKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQXNzZXRUcmFuc2ZlciwgJ1RyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcicpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0UmVjZWl2ZXIgPT09IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLCAnQXNzZXQgdHJhbnNmZXIgbXVzdCBiZSB0byBjb250cmFjdCcpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0QW1vdW50ID4gMCwgJ011c3QgcHJvdmlkZSBub24temVybyByZXdhcmRzJykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4ueGZlckFzc2V0ID09PSBhc3NldCwgJ0luY29ycmVjdCBhc3NldCBJRCcpCiAgICAvLyAKICAgIC8vICAgLy8gQWRkIHJld2FyZHMgdG8gdGhlIHBvb2wKICAgIC8vICAgdGhpcy5yZXdhcmRQb29sLnZhbHVlID0gdGhpcy5yZXdhcmRQb29sLnZhbHVlICsgeGZlclR4bi5hc3NldEFtb3VudAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIENhbGN1bGF0ZSBjdXJyZW50IEFQWSBiYXNlZCBvbiB0b3RhbCBzdGFrZWQgYW1vdW50CiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldEN1cnJlbnRBUFkoKTogdWludDY0IHsKICAgIC8vICAgY29uc3QgdG90YWxTdGFrZWQgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlCiAgICAvLyAKICAgIC8vICAgaWYgKHRvdGFsU3Rha2VkID09PSAwKSB7CiAgICAvLyAgICAgcmV0dXJuIDAgLy8gUmV0dXJuIDAgaWYgbm8gdG9rZW5zIHN0YWtlZAogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gQ2FsY3VsYXRlIGFubnVhbCByZXdhcmRzOiA1MiB3ZWVrcyAqIHdlZWtseVJld2FyZHMKICAgIC8vICAgY29uc3QgYW5udWFsUmV3YXJkczogdWludDY0ID0gNTIgKiB0aGlzLndlZWtseVJld2FyZHMudmFsdWUKICAgIC8vIAogICAgLy8gICAvLyBBUFkgPSAoYW5udWFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkKSAqIDEwMDAwIChpbiBiYXNpcyBwb2ludHMpCiAgICAvLyAgIGNvbnN0IGFweTogdWludDY0ID0gKGFubnVhbFJld2FyZHMgKiAxMDApIC8gdG90YWxTdGFrZWQKICAgIC8vIAogICAgLy8gICByZXR1cm4gYXB5CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IHBlbmRpbmcgcmV3YXJkcyBmb3IgYSBzcGVjaWZpYyB1c2VyCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldFBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogdWludDY0IHsKICAgIC8vICAgcmV0dXJuIHRoaXMuY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3MpCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogVHJpZ2dlciByZXdhcmQgZGlzdHJpYnV0aW9uIG1hbnVhbGx5IChhZG1pbiBvbmx5KQogICAgLy8gICogVXBkYXRlcyBhY2N1bXVsYXRlZCByZXdhcmRzIHBlciBzaGFyZSBpZiBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICogYW5kIGNvbXBvdW5kcyByZXdhcmRzIGZvciBhbGwgc3Rha2VycwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB0cmlnZ2VyUmV3YXJkRGlzdHJpYnV0aW9uKCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSBhZG1pbiBjYW4gdHJpZ2dlciBkaXN0cmlidXRpb24KICAgIC8vICAgY29uc3QgYWRtaW5BZGRyID0gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUKICAgIC8vICAgYXNzZXJ0KFR4bi5zZW5kZXIgPT09IGFkbWluQWRkciwgJ09ubHkgYWRtaW4gY2FuIHRyaWdnZXIgZGlzdHJpYnV0aW9uJykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgcmV3YXJkcwogICAgLy8gICB0aGlzLnVwZGF0ZVJld2FyZHMoKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCBhbGwgc3Rha2VycyBhbmQgY29tcG91bmQgdGhlaXIgcmV3YXJkcwogICAgLy8gICAvLyBOb3RlOiBJbiBBbGdvcmFuZCwgd2UgY2FuJ3QgaXRlcmF0ZSBvdmVyIGFsbCBib3hlcyBkaXJlY3RseQogICAgLy8gICAvLyBJbnN0ZWFkLCB3ZSdsbCByZWx5IG9uIHRoZSBmYWN0IHRoYXQgcmV3YXJkcyBhcmUgYXV0b21hdGljYWxseQogICAgLy8gICAvLyBjb21wb3VuZGVkIHdoZW4gdXNlcnMgaW50ZXJhY3Qgd2l0aCB0aGUgY29udHJhY3QgKHN0YWtlL3dpdGhkcmF3KQogICAgLy8gICAvLyBUaGlzIGlzIG1vcmUgZ2FzIGVmZmljaWVudCBhbmQgZm9sbG93cyBBbGdvcmFuZCdzIGRlc2lnbiBwYXR0ZXJucwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFVwZGF0ZSB0aGUgYWRtaW4gYWRkcmVzcwogICAgLy8gICogT25seSB0aGUgY3VycmVudCBhZG1pbiBjYW4gY2FsbCB0aGlzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHVwZGF0ZUFkbWluKG5ld0FkbWluQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiB1cGRhdGUgYWRtaW4nKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBhZG1pbiBhZGRyZXNzCiAgICAvLyAgIHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlID0gbmV3QWRtaW5BZGRyZXNzCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IGN1cnJlbnQgc3Rha2luZyBzdGF0aXN0aWNzIGZvciBhIHVzZXIKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCh7IHJlYWRvbmx5OiB0cnVlIH0pCiAgICAvLyBwdWJsaWMgZ2V0VXNlclN0YXRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogQXJyYXk8dWludDY0PiB7CiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcykKICAgIC8vICAgY29uc3QgcGVuZGluZ1Jld2FyZHMgPSB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHJlc3VsdDogdWludDY0W10gPSBbCiAgICAvLyAgICAgc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vICAgICBzdGFrZUluZm8ubGFzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUsCiAgICAvLyAgICAgcGVuZGluZ1Jld2FyZHMsCiAgICAvLyAgICAgc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcy5uYXRpdmUsCiAgICAvLyAgIF0KICAgIC8vIAogICAgLy8gICByZXR1cm4gcmVzdWx0CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IGNvbnRyYWN0IGdsb2JhbCBzdGF0aXN0aWNzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldENvbnRyYWN0U3RhdHMoKTogQXJyYXk8dWludDY0PiB7CiAgICAvLyAgIGNvbnN0IGN1cnJlbnRBUFkgPSB0aGlzLmdldEN1cnJlbnRBUFkoKQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHJlc3VsdDogdWludDY0W10gPSBbCiAgICAvLyAgICAgdGhpcy5hc3NldC52YWx1ZS5pZCwKICAgIC8vICAgICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlLAogICAgLy8gICAgIGN1cnJlbnRBUFksCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NjQKICAgIC8vIHB1YmxpYyByZXdhcmRQZXJpb2QgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICB1bmNvdmVyIDQKICAgIGl0b2IKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYtNDM2CiAgICAvLyBwdWJsaWMgdG90YWxTdGFrZWQgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgbGFzdFJld2FyZFRpbWUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgbWluaW11bVN0YWtlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIHJld2FyZFBvb2wgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyAKICAgIC8vIC8vIENvbnN0YW50cyBmb3IgZml4ZWQgcmV3YXJkIHN5c3RlbSAtIG5vdyBhcyBHbG9iYWxTdGF0ZSBmb3IgZmxleGliaWxpdHkKICAgIC8vIHB1YmxpYyB3ZWVrbHlSZXdhcmRzID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIHJld2FyZFBlcmlvZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIAogICAgLy8gcHVibGljIHN0YWtlcnMgPSBCb3hNYXA8QWNjb3VudCwgVXNlclN0YWtlSW5mbz4oeyBrZXlQcmVmaXg6ICdzdGFrZXJzJyB9KQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byByZWFkIHVzZXIgc3Rha2UgaW5mbyBmcm9tIGJveCBzdG9yYWdlCiAgICAvLyAgKi8KICAgIC8vIHB1YmxpYyBnZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogVXNlclN0YWtlSW5mbyB7CiAgICAvLyAgIGNvbnN0IHVzZXJCb3ggPSB0aGlzLnN0YWtlcnModXNlckFkZHJlc3MpCiAgICAvLyAKICAgIC8vICAgaWYgKHVzZXJCb3guZXhpc3RzKSB7CiAgICAvLyAgICAgcmV0dXJuIHVzZXJCb3gudmFsdWUuY29weSgpCiAgICAvLyAgIH0gZWxzZSB7CiAgICAvLyAgICAgcmV0dXJuIG5ldyBVc2VyU3Rha2VJbmZvKHsKICAgIC8vICAgICAgIHN0YWtlZEFtb3VudDogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIGZpcnN0U3Rha2VUaW1lOiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICAgICAgbGFzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIHRvdGFsUmV3YXJkc0Vhcm5lZDogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIHJld2FyZERlYnQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICBwZW5kaW5nUmV3YXJkczogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICB9KQogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSGVscGVyIGZ1bmN0aW9uIHRvIHN0b3JlIHVzZXIgc3Rha2UgaW5mbyBpbiBib3ggc3RvcmFnZQogICAgLy8gICovCiAgICAvLyBwdWJsaWMgc3RvcmVVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50LCBzdGFrZUluZm86IFVzZXJTdGFrZUluZm8pOiB2b2lkIHsKICAgIC8vICAgdGhpcy5zdGFrZXJzKHVzZXJBZGRyZXNzKS52YWx1ZSA9IHN0YWtlSW5mby5jb3B5KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUgaWYgcmV3YXJkIHBlcmlvZCBoYXMgcGFzc2VkCiAgICAvLyAgKi8KICAgIC8vIHByaXZhdGUgdXBkYXRlUmV3YXJkcygpOiB2b2lkIHsKICAgIC8vICAgY29uc3QgY3VycmVudFRpbWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICAvLyAgIGNvbnN0IGxhc3RSZXdhcmQgPSB0aGlzLmxhc3RSZXdhcmRUaW1lLnZhbHVlCiAgICAvLyAgIGNvbnN0IHJld2FyZFBlcmlvZCA9IHRoaXMucmV3YXJkUGVyaW9kLnZhbHVlCiAgICAvLyAKICAgIC8vICAgLy8gQ2hlY2sgaWYgYSBmdWxsIHJld2FyZCBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICBpZiAoY3VycmVudFRpbWUgPj0gbGFzdFJld2FyZCArIHJld2FyZFBlcmlvZCAmJiB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID4gMCkgewogICAgLy8gICAgIC8vIENhbGN1bGF0ZSBob3cgbWFueSBjb21wbGV0ZSBwZXJpb2RzIGhhdmUgcGFzc2VkCiAgICAvLyAgICAgY29uc3QgcGVyaW9kc1Bhc3NlZDogdWludDY0ID0gKGN1cnJlbnRUaW1lIC0gbGFzdFJld2FyZCkgLyByZXdhcmRQZXJpb2QKICAgIC8vIAogICAgLy8gICAgIC8vIFVwZGF0ZSBhY2N1bXVsYXRlZCByZXdhcmRzIHBlciBzaGFyZQogICAgLy8gICAgIGNvbnN0IHJld2FyZFBlclBlcmlvZCA9IHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZQogICAgLy8gICAgIGNvbnN0IHRvdGFsUmV3YXJkczogdWludDY0ID0gcmV3YXJkUGVyUGVyaW9kICogcGVyaW9kc1Bhc3NlZAogICAgLy8gCiAgICAvLyAgICAgLy8gU2ltcGxlIGRpdmlzaW9uIC0gcmV3YXJkcyBwZXIgdG9rZW4gc3Rha2VkCiAgICAvLyAgICAgY29uc3QgdG90YWxTdGFrZWQgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlCiAgICAvLyAgICAgY29uc3QgcmV3YXJkUGVyU2hhcmU6IHVpbnQ2NCA9IHRvdGFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUKICAgIC8vICAgICB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlID0gdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSArIHJld2FyZFBlclNoYXJlCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgbGFzdCByZXdhcmQgdGltZSB0byB0aGUgbW9zdCByZWNlbnQgY29tcGxldGUgcGVyaW9kCiAgICAvLyAgICAgdGhpcy5sYXN0UmV3YXJkVGltZS52YWx1ZSA9IGxhc3RSZXdhcmQgKyAocGVyaW9kc1Bhc3NlZCAqIHJld2FyZFBlcmlvZCkKICAgIC8vIAogICAgLy8gICAgIC8vIERlZHVjdCByZXdhcmRzIGZyb20gcG9vbAogICAgLy8gICAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IHRoaXMucmV3YXJkUG9vbC52YWx1ZSAtIHRvdGFsUmV3YXJkcwogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogQ2FsY3VsYXRlIHBlbmRpbmcgcmV3YXJkcyBmb3IgYSB1c2VyCiAgICAvLyAgKi8KICAgIC8vIHByaXZhdGUgY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3M6IEFjY291bnQpOiB1aW50NjQgewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAKICAgIC8vICAgaWYgKHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlID09PSAwKSB7CiAgICAvLyAgICAgcmV0dXJuIDAKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHVzZXJTdGFrZSA9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlCiAgICAvLyAgIGNvbnN0IGFjY1Jld2FyZHNQZXJTaGFyZSA9IHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUKICAgIC8vICAgY29uc3QgdXNlclJld2FyZERlYnQgPSBzdGFrZUluZm8ucmV3YXJkRGVidC5uYXRpdmUKICAgIC8vIAogICAgLy8gICAvLyBTaW1wbGUgY2FsY3VsYXRpb24gd2l0aG91dCBwcmVjaXNpb24KICAgIC8vICAgY29uc3QgdG90YWxFYXJuZWQ6IHVpbnQ2NCA9IHVzZXJTdGFrZSAqIGFjY1Jld2FyZHNQZXJTaGFyZQogICAgLy8gICBjb25zdCBwZW5kaW5nUmV3YXJkczogdWludDY0ID0gdG90YWxFYXJuZWQgPiB1c2VyUmV3YXJkRGVidCA/IHRvdGFsRWFybmVkIC0gdXNlclJld2FyZERlYnQgOiAwCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIHBlbmRpbmdSZXdhcmRzCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSGVscGVyIGZ1bmN0aW9uIHRvIGNvbXBvdW5kIHJld2FyZHMgZm9yIGEgdXNlcgogICAgLy8gICovCiAgICAvLyBwcml2YXRlIGNvbXBvdW5kUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA+IDApIHsKICAgIC8vICAgICBjb25zdCBwZW5kaW5nUmV3YXJkcyA9IHRoaXMuY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3MpCiAgICAvLyAgICAgaWYgKHBlbmRpbmdSZXdhcmRzID4gMCkgewogICAgLy8gICAgICAgLy8gQWRkIHJld2FyZHMgdG8gc3Rha2UKICAgIC8vICAgICAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICsgcGVuZGluZ1Jld2FyZHMpCiAgICAvLyAgICAgICBzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkLm5hdGl2ZSArIHBlbmRpbmdSZXdhcmRzKQogICAgLy8gICAgICAgc3Rha2VJbmZvLnJld2FyZERlYnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICogdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSkKICAgIC8vICAgICAgIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcyA9IG5ldyBhcmM0LlVpbnRONjQoMCkKICAgIC8vICAgICAgIHRoaXMuc3RvcmVVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgICAgIC8vIFVwZGF0ZSB0b3RhbCBzdGFrZWQKICAgIC8vICAgICAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlICsgcGVuZGluZ1Jld2FyZHMKICAgIC8vICAgICB9CiAgICAvLyAgIH0KICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBJbml0aWFsaXplIHRoZSBjb250cmFjdCB3aXRoIHRoZSBBU0EgdG9rZW4gSUQgYW5kIG90aGVyIHBhcmFtZXRlcnMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgaW5pdGlhbGl6ZSgKICAgIC8vICAgYXNzZXQ6IEFzc2V0LAogICAgLy8gICBhZG1pbkFkZHJlc3M6IEFjY291bnQsCiAgICAvLyAgIG1pbmltdW1TdGFrZTogdWludDY0LAogICAgLy8gICB3ZWVrbHlSZXdhcmRzOiB1aW50NjQsCiAgICAvLyAgIHJld2FyZFBlcmlvZDogdWludDY0LAogICAgLy8gKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGlzIG9ubHkgY2FsbGVkIGR1cmluZyBjb250cmFjdCBjcmVhdGlvbgogICAgLy8gICBhc3NlcnQodGhpcy5hc3NldC52YWx1ZSA9PT0gQXNzZXQoKSwgJ0FscmVhZHkgaW5pdGlhbGl6ZWQnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IHRoZSBjcmVhdG9yIGNhbiBpbml0aWFsaXplCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBHbG9iYWwuY3JlYXRvckFkZHJlc3MsICdPbmx5IGNyZWF0b3IgY2FuIGluaXRpYWxpemUnKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHRoZSBpbml0aWFsIHBhcmFtZXRlcnMKICAgIC8vICAgdGhpcy5hc3NldC52YWx1ZSA9IGFzc2V0CiAgICAvLyAgIHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlID0gYWRtaW5BZGRyZXNzCiAgICAvLyAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSAwCiAgICAvLyAgIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICAvLyAgIHRoaXMubWluaW11bVN0YWtlLnZhbHVlID0gbWluaW11bVN0YWtlCiAgICAvLyAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IDAKICAgIC8vICAgdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSA9IDAKICAgIC8vIAogICAgLy8gICAvLyBTZXQgcmV3YXJkIHN5c3RlbSBwYXJhbWV0ZXJzCiAgICAvLyAgIHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZSA9IHdlZWtseVJld2FyZHMKICAgIC8vICAgdGhpcy5yZXdhcmRQZXJpb2QudmFsdWUgPSByZXdhcmRQZXJpb2QKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBPcHQgdGhlIGNvbnRyYWN0IGludG8gdGhlIEFTQQogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyBvcHRJblRvQXNzZXQoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IHRoZSBjcmVhdG9yIG9yIGFkbWluIGNhbiBvcHQgaW4KICAgIC8vICAgY29uc3QgYWRtaW5BZGRyID0gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUKICAgIC8vICAgYXNzZXJ0KFR4bi5zZW5kZXIgPT09IEdsb2JhbC5jcmVhdG9yQWRkcmVzcyB8fCBUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGNyZWF0b3Igb3IgYWRtaW4gY2FuIG9wdCBpbicpCiAgICAvLyAKICAgIC8vICAgLy8gT3B0IHRoZSBjb250cmFjdCBpbnRvIHRoZSBBU0EKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGl0eG4KICAgIC8vICAgICAuYXNzZXRUcmFuc2Zlcih7CiAgICAvLyAgICAgICBhc3NldFJlY2VpdmVyOiBHbG9iYWwuY3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcywKICAgIC8vICAgICAgIGFzc2V0QW1vdW50OiAwLAogICAgLy8gICAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICB9KQogICAgLy8gICAgIC5zdWJtaXQoKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFN0YWtlIHRva2VucwogICAgLy8gICogUmVxdWlyZXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uCiAgICAvLyAgKiBBdXRvbWF0aWNhbGx5IGNsYWltcyBwZW5kaW5nIHJld2FyZHMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgc3Rha2UoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSB0aGUgY29udHJhY3QgaGFzIG9wdGVkIGludG8gdGhlIEFTQQogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgYXNzZXJ0KHRoaXMuYXNzZXQudmFsdWUgIT09IEFzc2V0KCksICdDb250cmFjdCBub3QgaW5pdGlhbGl6ZWQnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGNhbGwgaGFzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbgogICAgLy8gICBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBBU0EgdHJhbnNmZXIgZGV0YWlscwogICAgLy8gICBjb25zdCB4ZmVyVHhuID0gZ3R4bi5Bc3NldFRyYW5zZmVyVHhuKDApCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5Bc3NldFRyYW5zZmVyLCAnVHJhbnNhY3Rpb24gMCBtdXN0IGJlIGFzc2V0IHRyYW5zZmVyJykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4uYXNzZXRSZWNlaXZlciA9PT0gR2xvYmFsLmN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MsICdBc3NldCB0cmFuc2ZlciBtdXN0IGJlIHRvIGNvbnRyYWN0JykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4uYXNzZXRBbW91bnQgPiAwLCAnTXVzdCBzdGFrZSBub24temVybyBhbW91bnQnKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi54ZmVyQXNzZXQgPT09IGFzc2V0LCAnSW5jb3JyZWN0IGFzc2V0IElEJykKICAgIC8vIAogICAgLy8gICAvLyBHZXQgdGhlIHN0YWtlIGFtb3VudCBmcm9tIHRoZSB0cmFuc2FjdGlvbgogICAgLy8gICBjb25zdCBzdGFrZUFtb3VudCA9IHhmZXJUeG4uYXNzZXRBbW91bnQKICAgIC8vICAgY29uc3QgbWluaW11bVN0YWtlID0gdGhpcy5taW5pbXVtU3Rha2UudmFsdWUKICAgIC8vICAgY29uc3Qgc2VuZGVyQWRkcmVzcyA9IFR4bi5zZW5kZXIKICAgIC8vIAogICAgLy8gICAvLyBHZXQgdGhlIGN1cnJlbnQgdXNlciBzdGFrZSBpbmZvCiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIC8vIElmIHRoaXMgaXMgYSBuZXcgc3Rha2UsIGVuc3VyZSBpdCBtZWV0cyBtaW5pbXVtCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA9PT0gMCkgewogICAgLy8gICAgIGFzc2VydChzdGFrZUFtb3VudCA+PSBtaW5pbXVtU3Rha2UsICdJbml0aWFsIHN0YWtlIGJlbG93IG1pbmltdW0nKQogICAgLy8gICAgIC8vIFNldCB0aGUgZmlyc3Qgc3Rha2UgdGltZSAodGhpcyBuZXZlciBjaGFuZ2VzIGFmdGVyIGluaXRpYWwgc3Rha2UpCiAgICAvLyAgICAgc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lID0gbmV3IGFyYzQuVWludE42NChHbG9iYWwubGF0ZXN0VGltZXN0YW1wKQogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHN0YWtlIGluZm8gd2l0aCBuZXcgYW1vdW50CiAgICAvLyAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICsgc3Rha2VBbW91bnQpCiAgICAvLyAgIHN0YWtlSW5mby5sYXN0U3Rha2VUaW1lID0gbmV3IGFyYzQuVWludE42NChHbG9iYWwubGF0ZXN0VGltZXN0YW1wKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSByZXdhcmQgZGVidAogICAgLy8gICBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHVwZGF0ZWQgc3Rha2UgaW5mbwogICAgLy8gICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIGdsb2JhbCBzdGF0ZQogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHN0YWtlQW1vdW50CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogV2l0aGRyYXcgc3Rha2VkIHRva2VucwogICAgLy8gICogQXV0b21hdGljYWxseSBjbGFpbXMgcGVuZGluZyByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHdpdGhkcmF3KGFtb3VudDogdWludDY0KTogdm9pZCB7CiAgICAvLyAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBUeG4uc2VuZGVyCiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB1c2VyIGhhcyBlbm91Z2ggc3Rha2VkCiAgICAvLyAgIGFzc2VydChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA+IDAsICdObyBzdGFrZSBmb3VuZCcpCiAgICAvLyAgIGFzc2VydChhbW91bnQgPD0gc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsICdXaXRoZHJhd2FsIGFtb3VudCBleGNlZWRzIHN0YWtlJykKICAgIC8vICAgYXNzZXJ0KGFtb3VudCA+IDAsICdXaXRoZHJhd2FsIGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlJykKICAgIC8vIAogICAgLy8gICAvLyBJZiB3aXRoZHJhd2luZyBhbGwsIG5vIG5lZWQgdG8gY2hlY2sgbWluaW11bSByZW1haW5pbmcKICAgIC8vICAgLy8gSWYgcGFydGlhbCB3aXRoZHJhd2FsLCBlbnN1cmUgcmVtYWluaW5nIHN0YWtlIG1lZXRzIG1pbmltdW0KICAgIC8vICAgaWYgKGFtb3VudCA8IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlKSB7CiAgICAvLyAgICAgY29uc3QgcmVtYWluaW5nU3Rha2U6IHVpbnQ2NCA9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlIC0gYW1vdW50CiAgICAvLyAgICAgY29uc3QgbWluaW11bVN0YWtlID0gdGhpcy5taW5pbXVtU3Rha2UudmFsdWUKICAgIC8vICAgICBhc3NlcnQocmVtYWluaW5nU3Rha2UgPj0gbWluaW11bVN0YWtlLCAnUmVtYWluaW5nIHN0YWtlIHdvdWxkIGJlIGJlbG93IG1pbmltdW0nKQogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHN0YWtlIGluZm8KICAgIC8vICAgc3Rha2VJbmZvLnN0YWtlZEFtb3VudCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgLSBhbW91bnQpCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHJld2FyZCBkZWJ0CiAgICAvLyAgIHN0YWtlSW5mby5yZXdhcmREZWJ0ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAqIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUpCiAgICAvLyAKICAgIC8vICAgLy8gU3RvcmUgdXBkYXRlZCBzdGFrZSBpbmZvCiAgICAvLyAgIHRoaXMuc3RvcmVVc2VyU3Rha2VJbmZvKHNlbmRlckFkZHJlc3MsIHN0YWtlSW5mbykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgZ2xvYmFsIHN0YXRlCiAgICAvLyAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlIC0gYW1vdW50CiAgICAvLyAKICAgIC8vICAgLy8gVHJhbnNmZXIgdG9rZW5zIGJhY2sgdG8gdXNlcgogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgaXR4bgogICAgLy8gICAgIC5hc3NldFRyYW5zZmVyKHsKICAgIC8vICAgICAgIGFzc2V0UmVjZWl2ZXI6IHNlbmRlckFkZHJlc3MsCiAgICAvLyAgICAgICBhc3NldEFtb3VudDogYW1vdW50LAogICAgLy8gICAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICAgIGZlZTogMTAwMCwKICAgIC8vICAgICB9KQogICAgLy8gICAgIC5zdWJtaXQoKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEFkZCByZXdhcmRzIHRvIHRoZSByZXdhcmQgcG9vbAogICAgLy8gICogT25seSB0aGUgYWRtaW4gY2FuIGNhbGwgdGhpcwogICAgLy8gICogUmVxdWlyZXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggdGhlIHJld2FyZHMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgYWRkUmV3YXJkcygpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIGFkZCByZXdhcmRzCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiBhZGQgcmV3YXJkcycpCiAgICAvLyAKICAgIC8vICAgLy8gRW5zdXJlIHRoaXMgY2FsbCBoYXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggcmV3YXJkcwogICAgLy8gICBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBBU0EgdHJhbnNmZXIgZGV0YWlscwogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgY29uc3QgeGZlclR4biA9IGd0eG4uQXNzZXRUcmFuc2ZlclR4bigwKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQXNzZXRUcmFuc2ZlciwgJ1RyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcicpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0UmVjZWl2ZXIgPT09IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLCAnQXNzZXQgdHJhbnNmZXIgbXVzdCBiZSB0byBjb250cmFjdCcpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0QW1vdW50ID4gMCwgJ011c3QgcHJvdmlkZSBub24temVybyByZXdhcmRzJykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4ueGZlckFzc2V0ID09PSBhc3NldCwgJ0luY29ycmVjdCBhc3NldCBJRCcpCiAgICAvLyAKICAgIC8vICAgLy8gQWRkIHJld2FyZHMgdG8gdGhlIHBvb2wKICAgIC8vICAgdGhpcy5yZXdhcmRQb29sLnZhbHVlID0gdGhpcy5yZXdhcmRQb29sLnZhbHVlICsgeGZlclR4bi5hc3NldEFtb3VudAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIENhbGN1bGF0ZSBjdXJyZW50IEFQWSBiYXNlZCBvbiB0b3RhbCBzdGFrZWQgYW1vdW50CiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldEN1cnJlbnRBUFkoKTogdWludDY0IHsKICAgIC8vICAgY29uc3QgdG90YWxTdGFrZWQgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlCiAgICAvLyAKICAgIC8vICAgaWYgKHRvdGFsU3Rha2VkID09PSAwKSB7CiAgICAvLyAgICAgcmV0dXJuIDAgLy8gUmV0dXJuIDAgaWYgbm8gdG9rZW5zIHN0YWtlZAogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gQ2FsY3VsYXRlIGFubnVhbCByZXdhcmRzOiA1MiB3ZWVrcyAqIHdlZWtseVJld2FyZHMKICAgIC8vICAgY29uc3QgYW5udWFsUmV3YXJkczogdWludDY0ID0gNTIgKiB0aGlzLndlZWtseVJld2FyZHMudmFsdWUKICAgIC8vIAogICAgLy8gICAvLyBBUFkgPSAoYW5udWFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkKSAqIDEwMDAwIChpbiBiYXNpcyBwb2ludHMpCiAgICAvLyAgIGNvbnN0IGFweTogdWludDY0ID0gKGFubnVhbFJld2FyZHMgKiAxMDApIC8gdG90YWxTdGFrZWQKICAgIC8vIAogICAgLy8gICByZXR1cm4gYXB5CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IHBlbmRpbmcgcmV3YXJkcyBmb3IgYSBzcGVjaWZpYyB1c2VyCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldFBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogdWludDY0IHsKICAgIC8vICAgcmV0dXJuIHRoaXMuY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3MpCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogVHJpZ2dlciByZXdhcmQgZGlzdHJpYnV0aW9uIG1hbnVhbGx5IChhZG1pbiBvbmx5KQogICAgLy8gICogVXBkYXRlcyBhY2N1bXVsYXRlZCByZXdhcmRzIHBlciBzaGFyZSBpZiBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICogYW5kIGNvbXBvdW5kcyByZXdhcmRzIGZvciBhbGwgc3Rha2VycwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB0cmlnZ2VyUmV3YXJkRGlzdHJpYnV0aW9uKCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSBhZG1pbiBjYW4gdHJpZ2dlciBkaXN0cmlidXRpb24KICAgIC8vICAgY29uc3QgYWRtaW5BZGRyID0gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUKICAgIC8vICAgYXNzZXJ0KFR4bi5zZW5kZXIgPT09IGFkbWluQWRkciwgJ09ubHkgYWRtaW4gY2FuIHRyaWdnZXIgZGlzdHJpYnV0aW9uJykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgcmV3YXJkcwogICAgLy8gICB0aGlzLnVwZGF0ZVJld2FyZHMoKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCBhbGwgc3Rha2VycyBhbmQgY29tcG91bmQgdGhlaXIgcmV3YXJkcwogICAgLy8gICAvLyBOb3RlOiBJbiBBbGdvcmFuZCwgd2UgY2FuJ3QgaXRlcmF0ZSBvdmVyIGFsbCBib3hlcyBkaXJlY3RseQogICAgLy8gICAvLyBJbnN0ZWFkLCB3ZSdsbCByZWx5IG9uIHRoZSBmYWN0IHRoYXQgcmV3YXJkcyBhcmUgYXV0b21hdGljYWxseQogICAgLy8gICAvLyBjb21wb3VuZGVkIHdoZW4gdXNlcnMgaW50ZXJhY3Qgd2l0aCB0aGUgY29udHJhY3QgKHN0YWtlL3dpdGhkcmF3KQogICAgLy8gICAvLyBUaGlzIGlzIG1vcmUgZ2FzIGVmZmljaWVudCBhbmQgZm9sbG93cyBBbGdvcmFuZCdzIGRlc2lnbiBwYXR0ZXJucwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFVwZGF0ZSB0aGUgYWRtaW4gYWRkcmVzcwogICAgLy8gICogT25seSB0aGUgY3VycmVudCBhZG1pbiBjYW4gY2FsbCB0aGlzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHVwZGF0ZUFkbWluKG5ld0FkbWluQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiB1cGRhdGUgYWRtaW4nKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBhZG1pbiBhZGRyZXNzCiAgICAvLyAgIHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlID0gbmV3QWRtaW5BZGRyZXNzCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IGN1cnJlbnQgc3Rha2luZyBzdGF0aXN0aWNzIGZvciBhIHVzZXIKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCh7IHJlYWRvbmx5OiB0cnVlIH0pCiAgICAvLyBwdWJsaWMgZ2V0VXNlclN0YXRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogQXJyYXk8dWludDY0PiB7CiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcykKICAgIC8vICAgY29uc3QgcGVuZGluZ1Jld2FyZHMgPSB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHJlc3VsdDogdWludDY0W10gPSBbCiAgICAvLyAgICAgc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vICAgICBzdGFrZUluZm8ubGFzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUsCiAgICAvLyAgICAgcGVuZGluZ1Jld2FyZHMsCiAgICAvLyAgICAgc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcy5uYXRpdmUsCiAgICAvLyAgIF0KICAgIC8vIAogICAgLy8gICByZXR1cm4gcmVzdWx0CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IGNvbnRyYWN0IGdsb2JhbCBzdGF0aXN0aWNzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldENvbnRyYWN0U3RhdHMoKTogQXJyYXk8dWludDY0PiB7CiAgICAvLyAgIGNvbnN0IGN1cnJlbnRBUFkgPSB0aGlzLmdldEN1cnJlbnRBUFkoKQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHJlc3VsdDogdWludDY0W10gPSBbCiAgICAvLyAgICAgdGhpcy5hc3NldC52YWx1ZS5pZCwKICAgIC8vICAgICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlLAogICAgLy8gICAgIGN1cnJlbnRBUFksCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTgKICAgIC8vIHB1YmxpYyBtaW5pbXVtU3Rha2UgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICB1bmNvdmVyIDMKICAgIGl0b2IKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTYtNDM2CiAgICAvLyBwdWJsaWMgdG90YWxTdGFrZWQgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgbGFzdFJld2FyZFRpbWUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgbWluaW11bVN0YWtlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIHJld2FyZFBvb2wgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyBwdWJsaWMgYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyAKICAgIC8vIC8vIENvbnN0YW50cyBmb3IgZml4ZWQgcmV3YXJkIHN5c3RlbSAtIG5vdyBhcyBHbG9iYWxTdGF0ZSBmb3IgZmxleGliaWxpdHkKICAgIC8vIHB1YmxpYyB3ZWVrbHlSZXdhcmRzID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIHJld2FyZFBlcmlvZCA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIAogICAgLy8gcHVibGljIHN0YWtlcnMgPSBCb3hNYXA8QWNjb3VudCwgVXNlclN0YWtlSW5mbz4oeyBrZXlQcmVmaXg6ICdzdGFrZXJzJyB9KQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byByZWFkIHVzZXIgc3Rha2UgaW5mbyBmcm9tIGJveCBzdG9yYWdlCiAgICAvLyAgKi8KICAgIC8vIHB1YmxpYyBnZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogVXNlclN0YWtlSW5mbyB7CiAgICAvLyAgIGNvbnN0IHVzZXJCb3ggPSB0aGlzLnN0YWtlcnModXNlckFkZHJlc3MpCiAgICAvLyAKICAgIC8vICAgaWYgKHVzZXJCb3guZXhpc3RzKSB7CiAgICAvLyAgICAgcmV0dXJuIHVzZXJCb3gudmFsdWUuY29weSgpCiAgICAvLyAgIH0gZWxzZSB7CiAgICAvLyAgICAgcmV0dXJuIG5ldyBVc2VyU3Rha2VJbmZvKHsKICAgIC8vICAgICAgIHN0YWtlZEFtb3VudDogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIGZpcnN0U3Rha2VUaW1lOiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICAgICAgbGFzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIHRvdGFsUmV3YXJkc0Vhcm5lZDogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIHJld2FyZERlYnQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICBwZW5kaW5nUmV3YXJkczogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICB9KQogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSGVscGVyIGZ1bmN0aW9uIHRvIHN0b3JlIHVzZXIgc3Rha2UgaW5mbyBpbiBib3ggc3RvcmFnZQogICAgLy8gICovCiAgICAvLyBwdWJsaWMgc3RvcmVVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzOiBBY2NvdW50LCBzdGFrZUluZm86IFVzZXJTdGFrZUluZm8pOiB2b2lkIHsKICAgIC8vICAgdGhpcy5zdGFrZXJzKHVzZXJBZGRyZXNzKS52YWx1ZSA9IHN0YWtlSW5mby5jb3B5KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUgaWYgcmV3YXJkIHBlcmlvZCBoYXMgcGFzc2VkCiAgICAvLyAgKi8KICAgIC8vIHByaXZhdGUgdXBkYXRlUmV3YXJkcygpOiB2b2lkIHsKICAgIC8vICAgY29uc3QgY3VycmVudFRpbWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICAvLyAgIGNvbnN0IGxhc3RSZXdhcmQgPSB0aGlzLmxhc3RSZXdhcmRUaW1lLnZhbHVlCiAgICAvLyAgIGNvbnN0IHJld2FyZFBlcmlvZCA9IHRoaXMucmV3YXJkUGVyaW9kLnZhbHVlCiAgICAvLyAKICAgIC8vICAgLy8gQ2hlY2sgaWYgYSBmdWxsIHJld2FyZCBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICBpZiAoY3VycmVudFRpbWUgPj0gbGFzdFJld2FyZCArIHJld2FyZFBlcmlvZCAmJiB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID4gMCkgewogICAgLy8gICAgIC8vIENhbGN1bGF0ZSBob3cgbWFueSBjb21wbGV0ZSBwZXJpb2RzIGhhdmUgcGFzc2VkCiAgICAvLyAgICAgY29uc3QgcGVyaW9kc1Bhc3NlZDogdWludDY0ID0gKGN1cnJlbnRUaW1lIC0gbGFzdFJld2FyZCkgLyByZXdhcmRQZXJpb2QKICAgIC8vIAogICAgLy8gICAgIC8vIFVwZGF0ZSBhY2N1bXVsYXRlZCByZXdhcmRzIHBlciBzaGFyZQogICAgLy8gICAgIGNvbnN0IHJld2FyZFBlclBlcmlvZCA9IHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZQogICAgLy8gICAgIGNvbnN0IHRvdGFsUmV3YXJkczogdWludDY0ID0gcmV3YXJkUGVyUGVyaW9kICogcGVyaW9kc1Bhc3NlZAogICAgLy8gCiAgICAvLyAgICAgLy8gU2ltcGxlIGRpdmlzaW9uIC0gcmV3YXJkcyBwZXIgdG9rZW4gc3Rha2VkCiAgICAvLyAgICAgY29uc3QgdG90YWxTdGFrZWQgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlCiAgICAvLyAgICAgY29uc3QgcmV3YXJkUGVyU2hhcmU6IHVpbnQ2NCA9IHRvdGFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUKICAgIC8vICAgICB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlID0gdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSArIHJld2FyZFBlclNoYXJlCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgbGFzdCByZXdhcmQgdGltZSB0byB0aGUgbW9zdCByZWNlbnQgY29tcGxldGUgcGVyaW9kCiAgICAvLyAgICAgdGhpcy5sYXN0UmV3YXJkVGltZS52YWx1ZSA9IGxhc3RSZXdhcmQgKyAocGVyaW9kc1Bhc3NlZCAqIHJld2FyZFBlcmlvZCkKICAgIC8vIAogICAgLy8gICAgIC8vIERlZHVjdCByZXdhcmRzIGZyb20gcG9vbAogICAgLy8gICAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IHRoaXMucmV3YXJkUG9vbC52YWx1ZSAtIHRvdGFsUmV3YXJkcwogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogQ2FsY3VsYXRlIHBlbmRpbmcgcmV3YXJkcyBmb3IgYSB1c2VyCiAgICAvLyAgKi8KICAgIC8vIHByaXZhdGUgY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3M6IEFjY291bnQpOiB1aW50NjQgewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAKICAgIC8vICAgaWYgKHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlID09PSAwKSB7CiAgICAvLyAgICAgcmV0dXJuIDAKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHVzZXJTdGFrZSA9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlCiAgICAvLyAgIGNvbnN0IGFjY1Jld2FyZHNQZXJTaGFyZSA9IHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUKICAgIC8vICAgY29uc3QgdXNlclJld2FyZERlYnQgPSBzdGFrZUluZm8ucmV3YXJkRGVidC5uYXRpdmUKICAgIC8vIAogICAgLy8gICAvLyBTaW1wbGUgY2FsY3VsYXRpb24gd2l0aG91dCBwcmVjaXNpb24KICAgIC8vICAgY29uc3QgdG90YWxFYXJuZWQ6IHVpbnQ2NCA9IHVzZXJTdGFrZSAqIGFjY1Jld2FyZHNQZXJTaGFyZQogICAgLy8gICBjb25zdCBwZW5kaW5nUmV3YXJkczogdWludDY0ID0gdG90YWxFYXJuZWQgPiB1c2VyUmV3YXJkRGVidCA/IHRvdGFsRWFybmVkIC0gdXNlclJld2FyZERlYnQgOiAwCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIHBlbmRpbmdSZXdhcmRzCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSGVscGVyIGZ1bmN0aW9uIHRvIGNvbXBvdW5kIHJld2FyZHMgZm9yIGEgdXNlcgogICAgLy8gICovCiAgICAvLyBwcml2YXRlIGNvbXBvdW5kUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA+IDApIHsKICAgIC8vICAgICBjb25zdCBwZW5kaW5nUmV3YXJkcyA9IHRoaXMuY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3MpCiAgICAvLyAgICAgaWYgKHBlbmRpbmdSZXdhcmRzID4gMCkgewogICAgLy8gICAgICAgLy8gQWRkIHJld2FyZHMgdG8gc3Rha2UKICAgIC8vICAgICAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICsgcGVuZGluZ1Jld2FyZHMpCiAgICAvLyAgICAgICBzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8udG90YWxSZXdhcmRzRWFybmVkLm5hdGl2ZSArIHBlbmRpbmdSZXdhcmRzKQogICAgLy8gICAgICAgc3Rha2VJbmZvLnJld2FyZERlYnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICogdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSkKICAgIC8vICAgICAgIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcyA9IG5ldyBhcmM0LlVpbnRONjQoMCkKICAgIC8vICAgICAgIHRoaXMuc3RvcmVVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgICAgIC8vIFVwZGF0ZSB0b3RhbCBzdGFrZWQKICAgIC8vICAgICAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlICsgcGVuZGluZ1Jld2FyZHMKICAgIC8vICAgICB9CiAgICAvLyAgIH0KICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBJbml0aWFsaXplIHRoZSBjb250cmFjdCB3aXRoIHRoZSBBU0EgdG9rZW4gSUQgYW5kIG90aGVyIHBhcmFtZXRlcnMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgaW5pdGlhbGl6ZSgKICAgIC8vICAgYXNzZXQ6IEFzc2V0LAogICAgLy8gICBhZG1pbkFkZHJlc3M6IEFjY291bnQsCiAgICAvLyAgIG1pbmltdW1TdGFrZTogdWludDY0LAogICAgLy8gICB3ZWVrbHlSZXdhcmRzOiB1aW50NjQsCiAgICAvLyAgIHJld2FyZFBlcmlvZDogdWludDY0LAogICAgLy8gKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGlzIG9ubHkgY2FsbGVkIGR1cmluZyBjb250cmFjdCBjcmVhdGlvbgogICAgLy8gICBhc3NlcnQodGhpcy5hc3NldC52YWx1ZSA9PT0gQXNzZXQoKSwgJ0FscmVhZHkgaW5pdGlhbGl6ZWQnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IHRoZSBjcmVhdG9yIGNhbiBpbml0aWFsaXplCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBHbG9iYWwuY3JlYXRvckFkZHJlc3MsICdPbmx5IGNyZWF0b3IgY2FuIGluaXRpYWxpemUnKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHRoZSBpbml0aWFsIHBhcmFtZXRlcnMKICAgIC8vICAgdGhpcy5hc3NldC52YWx1ZSA9IGFzc2V0CiAgICAvLyAgIHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlID0gYWRtaW5BZGRyZXNzCiAgICAvLyAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSAwCiAgICAvLyAgIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBHbG9iYWwubGF0ZXN0VGltZXN0YW1wCiAgICAvLyAgIHRoaXMubWluaW11bVN0YWtlLnZhbHVlID0gbWluaW11bVN0YWtlCiAgICAvLyAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IDAKICAgIC8vICAgdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSA9IDAKICAgIC8vIAogICAgLy8gICAvLyBTZXQgcmV3YXJkIHN5c3RlbSBwYXJhbWV0ZXJzCiAgICAvLyAgIHRoaXMud2Vla2x5UmV3YXJkcy52YWx1ZSA9IHdlZWtseVJld2FyZHMKICAgIC8vICAgdGhpcy5yZXdhcmRQZXJpb2QudmFsdWUgPSByZXdhcmRQZXJpb2QKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBPcHQgdGhlIGNvbnRyYWN0IGludG8gdGhlIEFTQQogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyBvcHRJblRvQXNzZXQoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IHRoZSBjcmVhdG9yIG9yIGFkbWluIGNhbiBvcHQgaW4KICAgIC8vICAgY29uc3QgYWRtaW5BZGRyID0gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUKICAgIC8vICAgYXNzZXJ0KFR4bi5zZW5kZXIgPT09IEdsb2JhbC5jcmVhdG9yQWRkcmVzcyB8fCBUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGNyZWF0b3Igb3IgYWRtaW4gY2FuIG9wdCBpbicpCiAgICAvLyAKICAgIC8vICAgLy8gT3B0IHRoZSBjb250cmFjdCBpbnRvIHRoZSBBU0EKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGl0eG4KICAgIC8vICAgICAuYXNzZXRUcmFuc2Zlcih7CiAgICAvLyAgICAgICBhc3NldFJlY2VpdmVyOiBHbG9iYWwuY3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcywKICAgIC8vICAgICAgIGFzc2V0QW1vdW50OiAwLAogICAgLy8gICAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICB9KQogICAgLy8gICAgIC5zdWJtaXQoKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFN0YWtlIHRva2VucwogICAgLy8gICogUmVxdWlyZXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uCiAgICAvLyAgKiBBdXRvbWF0aWNhbGx5IGNsYWltcyBwZW5kaW5nIHJld2FyZHMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgc3Rha2UoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSB0aGUgY29udHJhY3QgaGFzIG9wdGVkIGludG8gdGhlIEFTQQogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgYXNzZXJ0KHRoaXMuYXNzZXQudmFsdWUgIT09IEFzc2V0KCksICdDb250cmFjdCBub3QgaW5pdGlhbGl6ZWQnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGNhbGwgaGFzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbgogICAgLy8gICBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBBU0EgdHJhbnNmZXIgZGV0YWlscwogICAgLy8gICBjb25zdCB4ZmVyVHhuID0gZ3R4bi5Bc3NldFRyYW5zZmVyVHhuKDApCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5Bc3NldFRyYW5zZmVyLCAnVHJhbnNhY3Rpb24gMCBtdXN0IGJlIGFzc2V0IHRyYW5zZmVyJykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4uYXNzZXRSZWNlaXZlciA9PT0gR2xvYmFsLmN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MsICdBc3NldCB0cmFuc2ZlciBtdXN0IGJlIHRvIGNvbnRyYWN0JykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4uYXNzZXRBbW91bnQgPiAwLCAnTXVzdCBzdGFrZSBub24temVybyBhbW91bnQnKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi54ZmVyQXNzZXQgPT09IGFzc2V0LCAnSW5jb3JyZWN0IGFzc2V0IElEJykKICAgIC8vIAogICAgLy8gICAvLyBHZXQgdGhlIHN0YWtlIGFtb3VudCBmcm9tIHRoZSB0cmFuc2FjdGlvbgogICAgLy8gICBjb25zdCBzdGFrZUFtb3VudCA9IHhmZXJUeG4uYXNzZXRBbW91bnQKICAgIC8vICAgY29uc3QgbWluaW11bVN0YWtlID0gdGhpcy5taW5pbXVtU3Rha2UudmFsdWUKICAgIC8vICAgY29uc3Qgc2VuZGVyQWRkcmVzcyA9IFR4bi5zZW5kZXIKICAgIC8vIAogICAgLy8gICAvLyBHZXQgdGhlIGN1cnJlbnQgdXNlciBzdGFrZSBpbmZvCiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIC8vIElmIHRoaXMgaXMgYSBuZXcgc3Rha2UsIGVuc3VyZSBpdCBtZWV0cyBtaW5pbXVtCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA9PT0gMCkgewogICAgLy8gICAgIGFzc2VydChzdGFrZUFtb3VudCA+PSBtaW5pbXVtU3Rha2UsICdJbml0aWFsIHN0YWtlIGJlbG93IG1pbmltdW0nKQogICAgLy8gICAgIC8vIFNldCB0aGUgZmlyc3Qgc3Rha2UgdGltZSAodGhpcyBuZXZlciBjaGFuZ2VzIGFmdGVyIGluaXRpYWwgc3Rha2UpCiAgICAvLyAgICAgc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lID0gbmV3IGFyYzQuVWludE42NChHbG9iYWwubGF0ZXN0VGltZXN0YW1wKQogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHN0YWtlIGluZm8gd2l0aCBuZXcgYW1vdW50CiAgICAvLyAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICsgc3Rha2VBbW91bnQpCiAgICAvLyAgIHN0YWtlSW5mby5sYXN0U3Rha2VUaW1lID0gbmV3IGFyYzQuVWludE42NChHbG9iYWwubGF0ZXN0VGltZXN0YW1wKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSByZXdhcmQgZGVidAogICAgLy8gICBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHVwZGF0ZWQgc3Rha2UgaW5mbwogICAgLy8gICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIGdsb2JhbCBzdGF0ZQogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHN0YWtlQW1vdW50CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogV2l0aGRyYXcgc3Rha2VkIHRva2VucwogICAgLy8gICogQXV0b21hdGljYWxseSBjbGFpbXMgcGVuZGluZyByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHdpdGhkcmF3KGFtb3VudDogdWludDY0KTogdm9pZCB7CiAgICAvLyAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBUeG4uc2VuZGVyCiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB1c2VyIGhhcyBlbm91Z2ggc3Rha2VkCiAgICAvLyAgIGFzc2VydChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA+IDAsICdObyBzdGFrZSBmb3VuZCcpCiAgICAvLyAgIGFzc2VydChhbW91bnQgPD0gc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsICdXaXRoZHJhd2FsIGFtb3VudCBleGNlZWRzIHN0YWtlJykKICAgIC8vICAgYXNzZXJ0KGFtb3VudCA+IDAsICdXaXRoZHJhd2FsIGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlJykKICAgIC8vIAogICAgLy8gICAvLyBJZiB3aXRoZHJhd2luZyBhbGwsIG5vIG5lZWQgdG8gY2hlY2sgbWluaW11bSByZW1haW5pbmcKICAgIC8vICAgLy8gSWYgcGFydGlhbCB3aXRoZHJhd2FsLCBlbnN1cmUgcmVtYWluaW5nIHN0YWtlIG1lZXRzIG1pbmltdW0KICAgIC8vICAgaWYgKGFtb3VudCA8IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlKSB7CiAgICAvLyAgICAgY29uc3QgcmVtYWluaW5nU3Rha2U6IHVpbnQ2NCA9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlIC0gYW1vdW50CiAgICAvLyAgICAgY29uc3QgbWluaW11bVN0YWtlID0gdGhpcy5taW5pbXVtU3Rha2UudmFsdWUKICAgIC8vICAgICBhc3NlcnQocmVtYWluaW5nU3Rha2UgPj0gbWluaW11bVN0YWtlLCAnUmVtYWluaW5nIHN0YWtlIHdvdWxkIGJlIGJlbG93IG1pbmltdW0nKQogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHN0YWtlIGluZm8KICAgIC8vICAgc3Rha2VJbmZvLnN0YWtlZEFtb3VudCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgLSBhbW91bnQpCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHJld2FyZCBkZWJ0CiAgICAvLyAgIHN0YWtlSW5mby5yZXdhcmREZWJ0ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAqIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUpCiAgICAvLyAKICAgIC8vICAgLy8gU3RvcmUgdXBkYXRlZCBzdGFrZSBpbmZvCiAgICAvLyAgIHRoaXMuc3RvcmVVc2VyU3Rha2VJbmZvKHNlbmRlckFkZHJlc3MsIHN0YWtlSW5mbykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgZ2xvYmFsIHN0YXRlCiAgICAvLyAgIHRoaXMudG90YWxTdGFrZWQudmFsdWUgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlIC0gYW1vdW50CiAgICAvLyAKICAgIC8vICAgLy8gVHJhbnNmZXIgdG9rZW5zIGJhY2sgdG8gdXNlcgogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgaXR4bgogICAgLy8gICAgIC5hc3NldFRyYW5zZmVyKHsKICAgIC8vICAgICAgIGFzc2V0UmVjZWl2ZXI6IHNlbmRlckFkZHJlc3MsCiAgICAvLyAgICAgICBhc3NldEFtb3VudDogYW1vdW50LAogICAgLy8gICAgICAgeGZlckFzc2V0OiBhc3NldCwKICAgIC8vICAgICAgIGZlZTogMTAwMCwKICAgIC8vICAgICB9KQogICAgLy8gICAgIC5zdWJtaXQoKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEFkZCByZXdhcmRzIHRvIHRoZSByZXdhcmQgcG9vbAogICAgLy8gICogT25seSB0aGUgYWRtaW4gY2FuIGNhbGwgdGhpcwogICAgLy8gICogUmVxdWlyZXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggdGhlIHJld2FyZHMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgYWRkUmV3YXJkcygpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIGFkZCByZXdhcmRzCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiBhZGQgcmV3YXJkcycpCiAgICAvLyAKICAgIC8vICAgLy8gRW5zdXJlIHRoaXMgY2FsbCBoYXMgYSBjb21wYW5pb24gQVNBIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggcmV3YXJkcwogICAgLy8gICBhc3NlcnQoR2xvYmFsLmdyb3VwU2l6ZSA9PT0gMiwgJ0V4cGVjdGVkIDIgdHhucyBpbiBncm91cCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBBU0EgdHJhbnNmZXIgZGV0YWlscwogICAgLy8gICBjb25zdCBhc3NldCA9IHRoaXMuYXNzZXQudmFsdWUKICAgIC8vICAgY29uc3QgeGZlclR4biA9IGd0eG4uQXNzZXRUcmFuc2ZlclR4bigwKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQXNzZXRUcmFuc2ZlciwgJ1RyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcicpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0UmVjZWl2ZXIgPT09IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLCAnQXNzZXQgdHJhbnNmZXIgbXVzdCBiZSB0byBjb250cmFjdCcpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0QW1vdW50ID4gMCwgJ011c3QgcHJvdmlkZSBub24temVybyByZXdhcmRzJykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4ueGZlckFzc2V0ID09PSBhc3NldCwgJ0luY29ycmVjdCBhc3NldCBJRCcpCiAgICAvLyAKICAgIC8vICAgLy8gQWRkIHJld2FyZHMgdG8gdGhlIHBvb2wKICAgIC8vICAgdGhpcy5yZXdhcmRQb29sLnZhbHVlID0gdGhpcy5yZXdhcmRQb29sLnZhbHVlICsgeGZlclR4bi5hc3NldEFtb3VudAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIENhbGN1bGF0ZSBjdXJyZW50IEFQWSBiYXNlZCBvbiB0b3RhbCBzdGFrZWQgYW1vdW50CiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldEN1cnJlbnRBUFkoKTogdWludDY0IHsKICAgIC8vICAgY29uc3QgdG90YWxTdGFrZWQgPSB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlCiAgICAvLyAKICAgIC8vICAgaWYgKHRvdGFsU3Rha2VkID09PSAwKSB7CiAgICAvLyAgICAgcmV0dXJuIDAgLy8gUmV0dXJuIDAgaWYgbm8gdG9rZW5zIHN0YWtlZAogICAgLy8gICB9CiAgICAvLyAKICAgIC8vICAgLy8gQ2FsY3VsYXRlIGFubnVhbCByZXdhcmRzOiA1MiB3ZWVrcyAqIHdlZWtseVJld2FyZHMKICAgIC8vICAgY29uc3QgYW5udWFsUmV3YXJkczogdWludDY0ID0gNTIgKiB0aGlzLndlZWtseVJld2FyZHMudmFsdWUKICAgIC8vIAogICAgLy8gICAvLyBBUFkgPSAoYW5udWFsUmV3YXJkcyAvIHRvdGFsU3Rha2VkKSAqIDEwMDAwIChpbiBiYXNpcyBwb2ludHMpCiAgICAvLyAgIGNvbnN0IGFweTogdWludDY0ID0gKGFubnVhbFJld2FyZHMgKiAxMDApIC8gdG90YWxTdGFrZWQKICAgIC8vIAogICAgLy8gICByZXR1cm4gYXB5CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IHBlbmRpbmcgcmV3YXJkcyBmb3IgYSBzcGVjaWZpYyB1c2VyCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldFBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogdWludDY0IHsKICAgIC8vICAgcmV0dXJuIHRoaXMuY2FsY3VsYXRlUGVuZGluZ1Jld2FyZHModXNlckFkZHJlc3MpCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogVHJpZ2dlciByZXdhcmQgZGlzdHJpYnV0aW9uIG1hbnVhbGx5IChhZG1pbiBvbmx5KQogICAgLy8gICogVXBkYXRlcyBhY2N1bXVsYXRlZCByZXdhcmRzIHBlciBzaGFyZSBpZiBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICogYW5kIGNvbXBvdW5kcyByZXdhcmRzIGZvciBhbGwgc3Rha2VycwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB0cmlnZ2VyUmV3YXJkRGlzdHJpYnV0aW9uKCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSBhZG1pbiBjYW4gdHJpZ2dlciBkaXN0cmlidXRpb24KICAgIC8vICAgY29uc3QgYWRtaW5BZGRyID0gdGhpcy5hZG1pbkFkZHJlc3MudmFsdWUKICAgIC8vICAgYXNzZXJ0KFR4bi5zZW5kZXIgPT09IGFkbWluQWRkciwgJ09ubHkgYWRtaW4gY2FuIHRyaWdnZXIgZGlzdHJpYnV0aW9uJykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgcmV3YXJkcwogICAgLy8gICB0aGlzLnVwZGF0ZVJld2FyZHMoKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCBhbGwgc3Rha2VycyBhbmQgY29tcG91bmQgdGhlaXIgcmV3YXJkcwogICAgLy8gICAvLyBOb3RlOiBJbiBBbGdvcmFuZCwgd2UgY2FuJ3QgaXRlcmF0ZSBvdmVyIGFsbCBib3hlcyBkaXJlY3RseQogICAgLy8gICAvLyBJbnN0ZWFkLCB3ZSdsbCByZWx5IG9uIHRoZSBmYWN0IHRoYXQgcmV3YXJkcyBhcmUgYXV0b21hdGljYWxseQogICAgLy8gICAvLyBjb21wb3VuZGVkIHdoZW4gdXNlcnMgaW50ZXJhY3Qgd2l0aCB0aGUgY29udHJhY3QgKHN0YWtlL3dpdGhkcmF3KQogICAgLy8gICAvLyBUaGlzIGlzIG1vcmUgZ2FzIGVmZmljaWVudCBhbmQgZm9sbG93cyBBbGdvcmFuZCdzIGRlc2lnbiBwYXR0ZXJucwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFVwZGF0ZSB0aGUgYWRtaW4gYWRkcmVzcwogICAgLy8gICogT25seSB0aGUgY3VycmVudCBhZG1pbiBjYW4gY2FsbCB0aGlzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHVwZGF0ZUFkbWluKG5ld0FkbWluQWRkcmVzczogQWNjb3VudCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiB1cGRhdGUgYWRtaW4nKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBhZG1pbiBhZGRyZXNzCiAgICAvLyAgIHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlID0gbmV3QWRtaW5BZGRyZXNzCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IGN1cnJlbnQgc3Rha2luZyBzdGF0aXN0aWNzIGZvciBhIHVzZXIKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCh7IHJlYWRvbmx5OiB0cnVlIH0pCiAgICAvLyBwdWJsaWMgZ2V0VXNlclN0YXRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogQXJyYXk8dWludDY0PiB7CiAgICAvLyAgIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcykKICAgIC8vICAgY29uc3QgcGVuZGluZ1Jld2FyZHMgPSB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHJlc3VsdDogdWludDY0W10gPSBbCiAgICAvLyAgICAgc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLmZpcnN0U3Rha2VUaW1lLm5hdGl2ZSwKICAgIC8vICAgICBzdGFrZUluZm8ubGFzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUsCiAgICAvLyAgICAgcGVuZGluZ1Jld2FyZHMsCiAgICAvLyAgICAgc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby5wZW5kaW5nUmV3YXJkcy5uYXRpdmUsCiAgICAvLyAgIF0KICAgIC8vIAogICAgLy8gICByZXR1cm4gcmVzdWx0CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogR2V0IGNvbnRyYWN0IGdsb2JhbCBzdGF0aXN0aWNzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldENvbnRyYWN0U3RhdHMoKTogQXJyYXk8dWludDY0PiB7CiAgICAvLyAgIGNvbnN0IGN1cnJlbnRBUFkgPSB0aGlzLmdldEN1cnJlbnRBUFkoKQogICAgLy8gCiAgICAvLyAgIGNvbnN0IHJlc3VsdDogdWludDY0W10gPSBbCiAgICAvLyAgICAgdGhpcy5hc3NldC52YWx1ZS5pZCwKICAgIC8vICAgICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlLAogICAgLy8gICAgIGN1cnJlbnRBUFksCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTkKICAgIC8vIHB1YmxpYyByZXdhcmRQb29sID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgdW5jb3ZlciAyCiAgICBpdG9iCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU2LTQzNgogICAgLy8gcHVibGljIHRvdGFsU3Rha2VkID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIGxhc3RSZXdhcmRUaW1lID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIG1pbmltdW1TdGFrZSA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIHB1YmxpYyByZXdhcmRQb29sID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIGFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gCiAgICAvLyAvLyBDb25zdGFudHMgZm9yIGZpeGVkIHJld2FyZCBzeXN0ZW0gLSBub3cgYXMgR2xvYmFsU3RhdGUgZm9yIGZsZXhpYmlsaXR5CiAgICAvLyBwdWJsaWMgd2Vla2x5UmV3YXJkcyA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIHB1YmxpYyByZXdhcmRQZXJpb2QgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyAKICAgIC8vIHB1YmxpYyBzdGFrZXJzID0gQm94TWFwPEFjY291bnQsIFVzZXJTdGFrZUluZm8+KHsga2V5UHJlZml4OiAnc3Rha2VycycgfSkKICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcmVhZCB1c2VyIHN0YWtlIGluZm8gZnJvbSBib3ggc3RvcmFnZQogICAgLy8gICovCiAgICAvLyBwdWJsaWMgZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCk6IFVzZXJTdGFrZUluZm8gewogICAgLy8gICBjb25zdCB1c2VyQm94ID0gdGhpcy5zdGFrZXJzKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGlmICh1c2VyQm94LmV4aXN0cykgewogICAgLy8gICAgIHJldHVybiB1c2VyQm94LnZhbHVlLmNvcHkoKQogICAgLy8gICB9IGVsc2UgewogICAgLy8gICAgIHJldHVybiBuZXcgVXNlclN0YWtlSW5mbyh7CiAgICAvLyAgICAgICBzdGFrZWRBbW91bnQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICBmaXJzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIGxhc3RTdGFrZVRpbWU6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICB0b3RhbFJld2FyZHNFYXJuZWQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICByZXdhcmREZWJ0OiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICAgICAgcGVuZGluZ1Jld2FyZHM6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgfSkKICAgIC8vICAgfQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byBzdG9yZSB1c2VyIHN0YWtlIGluZm8gaW4gYm94IHN0b3JhZ2UKICAgIC8vICAqLwogICAgLy8gcHVibGljIHN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCwgc3Rha2VJbmZvOiBVc2VyU3Rha2VJbmZvKTogdm9pZCB7CiAgICAvLyAgIHRoaXMuc3Rha2Vycyh1c2VyQWRkcmVzcykudmFsdWUgPSBzdGFrZUluZm8uY29weSgpCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogVXBkYXRlIGFjY3VtdWxhdGVkIHJld2FyZHMgcGVyIHNoYXJlIGlmIHJld2FyZCBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICovCiAgICAvLyBwcml2YXRlIHVwZGF0ZVJld2FyZHMoKTogdm9pZCB7CiAgICAvLyAgIGNvbnN0IGN1cnJlbnRUaW1lID0gR2xvYmFsLmxhdGVzdFRpbWVzdGFtcAogICAgLy8gICBjb25zdCBsYXN0UmV3YXJkID0gdGhpcy5sYXN0UmV3YXJkVGltZS52YWx1ZQogICAgLy8gICBjb25zdCByZXdhcmRQZXJpb2QgPSB0aGlzLnJld2FyZFBlcmlvZC52YWx1ZQogICAgLy8gCiAgICAvLyAgIC8vIENoZWNrIGlmIGEgZnVsbCByZXdhcmQgcGVyaW9kIGhhcyBwYXNzZWQKICAgIC8vICAgaWYgKGN1cnJlbnRUaW1lID49IGxhc3RSZXdhcmQgKyByZXdhcmRQZXJpb2QgJiYgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSA+IDApIHsKICAgIC8vICAgICAvLyBDYWxjdWxhdGUgaG93IG1hbnkgY29tcGxldGUgcGVyaW9kcyBoYXZlIHBhc3NlZAogICAgLy8gICAgIGNvbnN0IHBlcmlvZHNQYXNzZWQ6IHVpbnQ2NCA9IChjdXJyZW50VGltZSAtIGxhc3RSZXdhcmQpIC8gcmV3YXJkUGVyaW9kCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUKICAgIC8vICAgICBjb25zdCByZXdhcmRQZXJQZXJpb2QgPSB0aGlzLndlZWtseVJld2FyZHMudmFsdWUKICAgIC8vICAgICBjb25zdCB0b3RhbFJld2FyZHM6IHVpbnQ2NCA9IHJld2FyZFBlclBlcmlvZCAqIHBlcmlvZHNQYXNzZWQKICAgIC8vIAogICAgLy8gICAgIC8vIFNpbXBsZSBkaXZpc2lvbiAtIHJld2FyZHMgcGVyIHRva2VuIHN0YWtlZAogICAgLy8gICAgIGNvbnN0IHRvdGFsU3Rha2VkID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZQogICAgLy8gICAgIGNvbnN0IHJld2FyZFBlclNoYXJlOiB1aW50NjQgPSB0b3RhbFJld2FyZHMgLyB0b3RhbFN0YWtlZAogICAgLy8gCiAgICAvLyAgICAgLy8gVXBkYXRlIGFjY3VtdWxhdGVkIHJld2FyZHMgcGVyIHNoYXJlCiAgICAvLyAgICAgdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSA9IHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUgKyByZXdhcmRQZXJTaGFyZQogICAgLy8gCiAgICAvLyAgICAgLy8gVXBkYXRlIGxhc3QgcmV3YXJkIHRpbWUgdG8gdGhlIG1vc3QgcmVjZW50IGNvbXBsZXRlIHBlcmlvZAogICAgLy8gICAgIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBsYXN0UmV3YXJkICsgKHBlcmlvZHNQYXNzZWQgKiByZXdhcmRQZXJpb2QpCiAgICAvLyAKICAgIC8vICAgICAvLyBEZWR1Y3QgcmV3YXJkcyBmcm9tIHBvb2wKICAgIC8vICAgICB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSB0aGlzLnJld2FyZFBvb2wudmFsdWUgLSB0b3RhbFJld2FyZHMKICAgIC8vICAgfQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIENhbGN1bGF0ZSBwZW5kaW5nIHJld2FyZHMgZm9yIGEgdXNlcgogICAgLy8gICovCiAgICAvLyBwcml2YXRlIGNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogdWludDY0IHsKICAgIC8vICAgY29uc3Qgc3Rha2VJbmZvID0gdGhpcy5nZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA9PT0gMCkgewogICAgLy8gICAgIHJldHVybiAwCiAgICAvLyAgIH0KICAgIC8vIAogICAgLy8gICBjb25zdCB1c2VyU3Rha2UgPSBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZQogICAgLy8gICBjb25zdCBhY2NSZXdhcmRzUGVyU2hhcmUgPSB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlCiAgICAvLyAgIGNvbnN0IHVzZXJSZXdhcmREZWJ0ID0gc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlCiAgICAvLyAKICAgIC8vICAgLy8gU2ltcGxlIGNhbGN1bGF0aW9uIHdpdGhvdXQgcHJlY2lzaW9uCiAgICAvLyAgIGNvbnN0IHRvdGFsRWFybmVkOiB1aW50NjQgPSB1c2VyU3Rha2UgKiBhY2NSZXdhcmRzUGVyU2hhcmUKICAgIC8vICAgY29uc3QgcGVuZGluZ1Jld2FyZHM6IHVpbnQ2NCA9IHRvdGFsRWFybmVkID4gdXNlclJld2FyZERlYnQgPyB0b3RhbEVhcm5lZCAtIHVzZXJSZXdhcmREZWJ0IDogMAogICAgLy8gCiAgICAvLyAgIHJldHVybiBwZW5kaW5nUmV3YXJkcwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byBjb21wb3VuZCByZXdhcmRzIGZvciBhIHVzZXIKICAgIC8vICAqLwogICAgLy8gcHJpdmF0ZSBjb21wb3VuZFJld2FyZHModXNlckFkZHJlc3M6IEFjY291bnQpOiB2b2lkIHsKICAgIC8vICAgY29uc3Qgc3Rha2VJbmZvID0gdGhpcy5nZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzKQogICAgLy8gICBpZiAoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPiAwKSB7CiAgICAvLyAgICAgY29uc3QgcGVuZGluZ1Jld2FyZHMgPSB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gICAgIGlmIChwZW5kaW5nUmV3YXJkcyA+IDApIHsKICAgIC8vICAgICAgIC8vIEFkZCByZXdhcmRzIHRvIHN0YWtlCiAgICAvLyAgICAgICBzdGFrZUluZm8uc3Rha2VkQW1vdW50ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSArIHBlbmRpbmdSZXdhcmRzKQogICAgLy8gICAgICAgc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUgKyBwZW5kaW5nUmV3YXJkcykKICAgIC8vICAgICAgIHN0YWtlSW5mby5yZXdhcmREZWJ0ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAqIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUpCiAgICAvLyAgICAgICBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMgPSBuZXcgYXJjNC5VaW50TjY0KDApCiAgICAvLyAgICAgICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcywgc3Rha2VJbmZvKQogICAgLy8gCiAgICAvLyAgICAgICAvLyBVcGRhdGUgdG90YWwgc3Rha2VkCiAgICAvLyAgICAgICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHBlbmRpbmdSZXdhcmRzCiAgICAvLyAgICAgfQogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSW5pdGlhbGl6ZSB0aGUgY29udHJhY3Qgd2l0aCB0aGUgQVNBIHRva2VuIElEIGFuZCBvdGhlciBwYXJhbWV0ZXJzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIGluaXRpYWxpemUoCiAgICAvLyAgIGFzc2V0OiBBc3NldCwKICAgIC8vICAgYWRtaW5BZGRyZXNzOiBBY2NvdW50LAogICAgLy8gICBtaW5pbXVtU3Rha2U6IHVpbnQ2NCwKICAgIC8vICAgd2Vla2x5UmV3YXJkczogdWludDY0LAogICAgLy8gICByZXdhcmRQZXJpb2Q6IHVpbnQ2NCwKICAgIC8vICk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgdGhpcyBpcyBvbmx5IGNhbGxlZCBkdXJpbmcgY29udHJhY3QgY3JlYXRpb24KICAgIC8vICAgYXNzZXJ0KHRoaXMuYXNzZXQudmFsdWUgPT09IEFzc2V0KCksICdBbHJlYWR5IGluaXRpYWxpemVkJykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgb25seSB0aGUgY3JlYXRvciBjYW4gaW5pdGlhbGl6ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gR2xvYmFsLmNyZWF0b3JBZGRyZXNzLCAnT25seSBjcmVhdG9yIGNhbiBpbml0aWFsaXplJykKICAgIC8vIAogICAgLy8gICAvLyBTdG9yZSB0aGUgaW5pdGlhbCBwYXJhbWV0ZXJzCiAgICAvLyAgIHRoaXMuYXNzZXQudmFsdWUgPSBhc3NldAogICAgLy8gICB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZSA9IGFkbWluQWRkcmVzcwogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gMAogICAgLy8gICB0aGlzLmxhc3RSZXdhcmRUaW1lLnZhbHVlID0gR2xvYmFsLmxhdGVzdFRpbWVzdGFtcAogICAgLy8gICB0aGlzLm1pbmltdW1TdGFrZS52YWx1ZSA9IG1pbmltdW1TdGFrZQogICAgLy8gICB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSAwCiAgICAvLyAgIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUgPSAwCiAgICAvLyAKICAgIC8vICAgLy8gU2V0IHJld2FyZCBzeXN0ZW0gcGFyYW1ldGVycwogICAgLy8gICB0aGlzLndlZWtseVJld2FyZHMudmFsdWUgPSB3ZWVrbHlSZXdhcmRzCiAgICAvLyAgIHRoaXMucmV3YXJkUGVyaW9kLnZhbHVlID0gcmV3YXJkUGVyaW9kCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogT3B0IHRoZSBjb250cmFjdCBpbnRvIHRoZSBBU0EKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgb3B0SW5Ub0Fzc2V0KCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSB0aGUgY3JlYXRvciBvciBhZG1pbiBjYW4gb3B0IGluCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBHbG9iYWwuY3JlYXRvckFkZHJlc3MgfHwgVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBjcmVhdG9yIG9yIGFkbWluIGNhbiBvcHQgaW4nKQogICAgLy8gCiAgICAvLyAgIC8vIE9wdCB0aGUgY29udHJhY3QgaW50byB0aGUgQVNBCiAgICAvLyAgIGNvbnN0IGFzc2V0ID0gdGhpcy5hc3NldC52YWx1ZQogICAgLy8gICBpdHhuCiAgICAvLyAgICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgICAgYXNzZXRSZWNlaXZlcjogR2xvYmFsLmN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MsCiAgICAvLyAgICAgICBhc3NldEFtb3VudDogMCwKICAgIC8vICAgICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgICAgfSkKICAgIC8vICAgICAuc3VibWl0KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBTdGFrZSB0b2tlbnMKICAgIC8vICAqIFJlcXVpcmVzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbgogICAgLy8gICogQXV0b21hdGljYWxseSBjbGFpbXMgcGVuZGluZyByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHN0YWtlKCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgdGhlIGNvbnRyYWN0IGhhcyBvcHRlZCBpbnRvIHRoZSBBU0EKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGFzc2VydCh0aGlzLmFzc2V0LnZhbHVlICE9PSBBc3NldCgpLCAnQ29udHJhY3Qgbm90IGluaXRpYWxpemVkJykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgdGhpcyBjYWxsIGhhcyBhIGNvbXBhbmlvbiBBU0EgdHJhbnNmZXIgdHJhbnNhY3Rpb24KICAgIC8vICAgYXNzZXJ0KEdsb2JhbC5ncm91cFNpemUgPT09IDIsICdFeHBlY3RlZCAyIHR4bnMgaW4gZ3JvdXAnKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCB0aGUgQVNBIHRyYW5zZmVyIGRldGFpbHMKICAgIC8vICAgY29uc3QgeGZlclR4biA9IGd0eG4uQXNzZXRUcmFuc2ZlclR4bigwKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQXNzZXRUcmFuc2ZlciwgJ1RyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcicpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0UmVjZWl2ZXIgPT09IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLCAnQXNzZXQgdHJhbnNmZXIgbXVzdCBiZSB0byBjb250cmFjdCcpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0QW1vdW50ID4gMCwgJ011c3Qgc3Rha2Ugbm9uLXplcm8gYW1vdW50JykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4ueGZlckFzc2V0ID09PSBhc3NldCwgJ0luY29ycmVjdCBhc3NldCBJRCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBzdGFrZSBhbW91bnQgZnJvbSB0aGUgdHJhbnNhY3Rpb24KICAgIC8vICAgY29uc3Qgc3Rha2VBbW91bnQgPSB4ZmVyVHhuLmFzc2V0QW1vdW50CiAgICAvLyAgIGNvbnN0IG1pbmltdW1TdGFrZSA9IHRoaXMubWluaW11bVN0YWtlLnZhbHVlCiAgICAvLyAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBUeG4uc2VuZGVyCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBjdXJyZW50IHVzZXIgc3Rha2UgaW5mbwogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICAvLyBJZiB0aGlzIGlzIGEgbmV3IHN0YWtlLCBlbnN1cmUgaXQgbWVldHMgbWluaW11bQogICAgLy8gICBpZiAoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPT09IDApIHsKICAgIC8vICAgICBhc3NlcnQoc3Rha2VBbW91bnQgPj0gbWluaW11bVN0YWtlLCAnSW5pdGlhbCBzdGFrZSBiZWxvdyBtaW5pbXVtJykKICAgIC8vICAgICAvLyBTZXQgdGhlIGZpcnN0IHN0YWtlIHRpbWUgKHRoaXMgbmV2ZXIgY2hhbmdlcyBhZnRlciBpbml0aWFsIHN0YWtlKQogICAgLy8gICAgIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZSA9IG5ldyBhcmM0LlVpbnRONjQoR2xvYmFsLmxhdGVzdFRpbWVzdGFtcCkKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBzdGFrZSBpbmZvIHdpdGggbmV3IGFtb3VudAogICAgLy8gICBzdGFrZUluZm8uc3Rha2VkQW1vdW50ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSArIHN0YWtlQW1vdW50KQogICAgLy8gICBzdGFrZUluZm8ubGFzdFN0YWtlVGltZSA9IG5ldyBhcmM0LlVpbnRONjQoR2xvYmFsLmxhdGVzdFRpbWVzdGFtcCkKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgcmV3YXJkIGRlYnQKICAgIC8vICAgc3Rha2VJbmZvLnJld2FyZERlYnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICogdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSkKICAgIC8vIAogICAgLy8gICAvLyBTdG9yZSB1cGRhdGVkIHN0YWtlIGluZm8KICAgIC8vICAgdGhpcy5zdG9yZVVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcywgc3Rha2VJbmZvKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBnbG9iYWwgc3RhdGUKICAgIC8vICAgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSA9IHRoaXMudG90YWxTdGFrZWQudmFsdWUgKyBzdGFrZUFtb3VudAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFdpdGhkcmF3IHN0YWtlZCB0b2tlbnMKICAgIC8vICAqIEF1dG9tYXRpY2FsbHkgY2xhaW1zIHBlbmRpbmcgcmV3YXJkcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB3aXRoZHJhdyhhbW91bnQ6IHVpbnQ2NCk6IHZvaWQgewogICAgLy8gICBjb25zdCBzZW5kZXJBZGRyZXNzID0gVHhuLnNlbmRlcgogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgdXNlciBoYXMgZW5vdWdoIHN0YWtlZAogICAgLy8gICBhc3NlcnQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPiAwLCAnTm8gc3Rha2UgZm91bmQnKQogICAgLy8gICBhc3NlcnQoYW1vdW50IDw9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLCAnV2l0aGRyYXdhbCBhbW91bnQgZXhjZWVkcyBzdGFrZScpCiAgICAvLyAgIGFzc2VydChhbW91bnQgPiAwLCAnV2l0aGRyYXdhbCBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZScpCiAgICAvLyAKICAgIC8vICAgLy8gSWYgd2l0aGRyYXdpbmcgYWxsLCBubyBuZWVkIHRvIGNoZWNrIG1pbmltdW0gcmVtYWluaW5nCiAgICAvLyAgIC8vIElmIHBhcnRpYWwgd2l0aGRyYXdhbCwgZW5zdXJlIHJlbWFpbmluZyBzdGFrZSBtZWV0cyBtaW5pbXVtCiAgICAvLyAgIGlmIChhbW91bnQgPCBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSkgewogICAgLy8gICAgIGNvbnN0IHJlbWFpbmluZ1N0YWtlOiB1aW50NjQgPSBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAtIGFtb3VudAogICAgLy8gICAgIGNvbnN0IG1pbmltdW1TdGFrZSA9IHRoaXMubWluaW11bVN0YWtlLnZhbHVlCiAgICAvLyAgICAgYXNzZXJ0KHJlbWFpbmluZ1N0YWtlID49IG1pbmltdW1TdGFrZSwgJ1JlbWFpbmluZyBzdGFrZSB3b3VsZCBiZSBiZWxvdyBtaW5pbXVtJykKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBzdGFrZSBpbmZvCiAgICAvLyAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlIC0gYW1vdW50KQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSByZXdhcmQgZGVidAogICAgLy8gICBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHVwZGF0ZWQgc3Rha2UgaW5mbwogICAgLy8gICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIGdsb2JhbCBzdGF0ZQogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSAtIGFtb3VudAogICAgLy8gCiAgICAvLyAgIC8vIFRyYW5zZmVyIHRva2VucyBiYWNrIHRvIHVzZXIKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGl0eG4KICAgIC8vICAgICAuYXNzZXRUcmFuc2Zlcih7CiAgICAvLyAgICAgICBhc3NldFJlY2VpdmVyOiBzZW5kZXJBZGRyZXNzLAogICAgLy8gICAgICAgYXNzZXRBbW91bnQ6IGFtb3VudCwKICAgIC8vICAgICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgICAgICBmZWU6IDEwMDAsCiAgICAvLyAgICAgfSkKICAgIC8vICAgICAuc3VibWl0KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBBZGQgcmV3YXJkcyB0byB0aGUgcmV3YXJkIHBvb2wKICAgIC8vICAqIE9ubHkgdGhlIGFkbWluIGNhbiBjYWxsIHRoaXMKICAgIC8vICAqIFJlcXVpcmVzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aXRoIHRoZSByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIGFkZFJld2FyZHMoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IGFkbWluIGNhbiBhZGQgcmV3YXJkcwogICAgLy8gICBjb25zdCBhZG1pbkFkZHIgPSB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBhZG1pbiBjYW4gYWRkIHJld2FyZHMnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGNhbGwgaGFzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aXRoIHJld2FyZHMKICAgIC8vICAgYXNzZXJ0KEdsb2JhbC5ncm91cFNpemUgPT09IDIsICdFeHBlY3RlZCAyIHR4bnMgaW4gZ3JvdXAnKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCB0aGUgQVNBIHRyYW5zZmVyIGRldGFpbHMKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGNvbnN0IHhmZXJUeG4gPSBndHhuLkFzc2V0VHJhbnNmZXJUeG4oMCkKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkFzc2V0VHJhbnNmZXIsICdUcmFuc2FjdGlvbiAwIG11c3QgYmUgYXNzZXQgdHJhbnNmZXInKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi5hc3NldFJlY2VpdmVyID09PSBHbG9iYWwuY3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcywgJ0Fzc2V0IHRyYW5zZmVyIG11c3QgYmUgdG8gY29udHJhY3QnKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi5hc3NldEFtb3VudCA+IDAsICdNdXN0IHByb3ZpZGUgbm9uLXplcm8gcmV3YXJkcycpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLnhmZXJBc3NldCA9PT0gYXNzZXQsICdJbmNvcnJlY3QgYXNzZXQgSUQnKQogICAgLy8gCiAgICAvLyAgIC8vIEFkZCByZXdhcmRzIHRvIHRoZSBwb29sCiAgICAvLyAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IHRoaXMucmV3YXJkUG9vbC52YWx1ZSArIHhmZXJUeG4uYXNzZXRBbW91bnQKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBDYWxjdWxhdGUgY3VycmVudCBBUFkgYmFzZWQgb24gdG90YWwgc3Rha2VkIGFtb3VudAogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRDdXJyZW50QVBZKCk6IHVpbnQ2NCB7CiAgICAvLyAgIGNvbnN0IHRvdGFsU3Rha2VkID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZQogICAgLy8gCiAgICAvLyAgIGlmICh0b3RhbFN0YWtlZCA9PT0gMCkgewogICAgLy8gICAgIHJldHVybiAwIC8vIFJldHVybiAwIGlmIG5vIHRva2VucyBzdGFrZWQKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIENhbGN1bGF0ZSBhbm51YWwgcmV3YXJkczogNTIgd2Vla3MgKiB3ZWVrbHlSZXdhcmRzCiAgICAvLyAgIGNvbnN0IGFubnVhbFJld2FyZHM6IHVpbnQ2NCA9IDUyICogdGhpcy53ZWVrbHlSZXdhcmRzLnZhbHVlCiAgICAvLyAKICAgIC8vICAgLy8gQVBZID0gKGFubnVhbFJld2FyZHMgLyB0b3RhbFN0YWtlZCkgKiAxMDAwMCAoaW4gYmFzaXMgcG9pbnRzKQogICAgLy8gICBjb25zdCBhcHk6IHVpbnQ2NCA9IChhbm51YWxSZXdhcmRzICogMTAwKSAvIHRvdGFsU3Rha2VkCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIGFweQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBwZW5kaW5nIHJld2FyZHMgZm9yIGEgc3BlY2lmaWMgdXNlcgogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHVpbnQ2NCB7CiAgICAvLyAgIHJldHVybiB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFRyaWdnZXIgcmV3YXJkIGRpc3RyaWJ1dGlvbiBtYW51YWxseSAoYWRtaW4gb25seSkKICAgIC8vICAqIFVwZGF0ZXMgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUgaWYgcGVyaW9kIGhhcyBwYXNzZWQKICAgIC8vICAqIGFuZCBjb21wb3VuZHMgcmV3YXJkcyBmb3IgYWxsIHN0YWtlcnMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgdHJpZ2dlclJld2FyZERpc3RyaWJ1dGlvbigpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIHRyaWdnZXIgZGlzdHJpYnV0aW9uCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiB0cmlnZ2VyIGRpc3RyaWJ1dGlvbicpCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHJld2FyZHMKICAgIC8vICAgdGhpcy51cGRhdGVSZXdhcmRzKCkKICAgIC8vIAogICAgLy8gICAvLyBHZXQgYWxsIHN0YWtlcnMgYW5kIGNvbXBvdW5kIHRoZWlyIHJld2FyZHMKICAgIC8vICAgLy8gTm90ZTogSW4gQWxnb3JhbmQsIHdlIGNhbid0IGl0ZXJhdGUgb3ZlciBhbGwgYm94ZXMgZGlyZWN0bHkKICAgIC8vICAgLy8gSW5zdGVhZCwgd2UnbGwgcmVseSBvbiB0aGUgZmFjdCB0aGF0IHJld2FyZHMgYXJlIGF1dG9tYXRpY2FsbHkKICAgIC8vICAgLy8gY29tcG91bmRlZCB3aGVuIHVzZXJzIGludGVyYWN0IHdpdGggdGhlIGNvbnRyYWN0IChzdGFrZS93aXRoZHJhdykKICAgIC8vICAgLy8gVGhpcyBpcyBtb3JlIGdhcyBlZmZpY2llbnQgYW5kIGZvbGxvd3MgQWxnb3JhbmQncyBkZXNpZ24gcGF0dGVybnMKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBVcGRhdGUgdGhlIGFkbWluIGFkZHJlc3MKICAgIC8vICAqIE9ubHkgdGhlIGN1cnJlbnQgYWRtaW4gY2FuIGNhbGwgdGhpcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB1cGRhdGVBZG1pbihuZXdBZG1pbkFkZHJlc3M6IEFjY291bnQpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIHVwZGF0ZSBhZG1pbgogICAgLy8gICBjb25zdCBhZG1pbkFkZHIgPSB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluJykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgYWRtaW4gYWRkcmVzcwogICAgLy8gICB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZSA9IG5ld0FkbWluQWRkcmVzcwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBjdXJyZW50IHN0YWtpbmcgc3RhdGlzdGljcyBmb3IgYSB1c2VyCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldFVzZXJTdGF0cyh1c2VyQWRkcmVzczogQWNjb3VudCk6IEFycmF5PHVpbnQ2ND4gewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAgIGNvbnN0IHBlbmRpbmdSZXdhcmRzID0gdGhpcy5jYWxjdWxhdGVQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICBjb25zdCByZXN1bHQ6IHVpbnQ2NFtdID0gWwogICAgLy8gICAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLmxhc3RTdGFrZVRpbWUubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby50b3RhbFJld2FyZHNFYXJuZWQubmF0aXZlLAogICAgLy8gICAgIHBlbmRpbmdSZXdhcmRzLAogICAgLy8gICAgIHN0YWtlSW5mby5yZXdhcmREZWJ0Lm5hdGl2ZSwKICAgIC8vICAgICBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMubmF0aXZlLAogICAgLy8gICBdCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIHJlc3VsdAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBjb250cmFjdCBnbG9iYWwgc3RhdGlzdGljcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRDb250cmFjdFN0YXRzKCk6IEFycmF5PHVpbnQ2ND4gewogICAgLy8gICBjb25zdCBjdXJyZW50QVBZID0gdGhpcy5nZXRDdXJyZW50QVBZKCkKICAgIC8vIAogICAgLy8gICBjb25zdCByZXN1bHQ6IHVpbnQ2NFtdID0gWwogICAgLy8gICAgIHRoaXMuYXNzZXQudmFsdWUuaWQsCiAgICAvLyAgICAgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSwKICAgIC8vICAgICBjdXJyZW50QVBZLAogICAgY29uY2F0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjYwCiAgICAvLyBwdWJsaWMgYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBzd2FwCiAgICBpdG9iCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU2LTQzNgogICAgLy8gcHVibGljIHRvdGFsU3Rha2VkID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIGxhc3RSZXdhcmRUaW1lID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIG1pbmltdW1TdGFrZSA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIHB1YmxpYyByZXdhcmRQb29sID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gcHVibGljIGFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgLy8gCiAgICAvLyAvLyBDb25zdGFudHMgZm9yIGZpeGVkIHJld2FyZCBzeXN0ZW0gLSBub3cgYXMgR2xvYmFsU3RhdGUgZm9yIGZsZXhpYmlsaXR5CiAgICAvLyBwdWJsaWMgd2Vla2x5UmV3YXJkcyA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIC8vIHB1YmxpYyByZXdhcmRQZXJpb2QgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICAvLyAKICAgIC8vIHB1YmxpYyBzdGFrZXJzID0gQm94TWFwPEFjY291bnQsIFVzZXJTdGFrZUluZm8+KHsga2V5UHJlZml4OiAnc3Rha2VycycgfSkKICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcmVhZCB1c2VyIHN0YWtlIGluZm8gZnJvbSBib3ggc3RvcmFnZQogICAgLy8gICovCiAgICAvLyBwdWJsaWMgZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCk6IFVzZXJTdGFrZUluZm8gewogICAgLy8gICBjb25zdCB1c2VyQm94ID0gdGhpcy5zdGFrZXJzKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGlmICh1c2VyQm94LmV4aXN0cykgewogICAgLy8gICAgIHJldHVybiB1c2VyQm94LnZhbHVlLmNvcHkoKQogICAgLy8gICB9IGVsc2UgewogICAgLy8gICAgIHJldHVybiBuZXcgVXNlclN0YWtlSW5mbyh7CiAgICAvLyAgICAgICBzdGFrZWRBbW91bnQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICBmaXJzdFN0YWtlVGltZTogbmV3IGFyYzQuVWludE42NCgwKSwKICAgIC8vICAgICAgIGxhc3RTdGFrZVRpbWU6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICB0b3RhbFJld2FyZHNFYXJuZWQ6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgICByZXdhcmREZWJ0OiBuZXcgYXJjNC5VaW50TjY0KDApLAogICAgLy8gICAgICAgcGVuZGluZ1Jld2FyZHM6IG5ldyBhcmM0LlVpbnRONjQoMCksCiAgICAvLyAgICAgfSkKICAgIC8vICAgfQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byBzdG9yZSB1c2VyIHN0YWtlIGluZm8gaW4gYm94IHN0b3JhZ2UKICAgIC8vICAqLwogICAgLy8gcHVibGljIHN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzczogQWNjb3VudCwgc3Rha2VJbmZvOiBVc2VyU3Rha2VJbmZvKTogdm9pZCB7CiAgICAvLyAgIHRoaXMuc3Rha2Vycyh1c2VyQWRkcmVzcykudmFsdWUgPSBzdGFrZUluZm8uY29weSgpCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogVXBkYXRlIGFjY3VtdWxhdGVkIHJld2FyZHMgcGVyIHNoYXJlIGlmIHJld2FyZCBwZXJpb2QgaGFzIHBhc3NlZAogICAgLy8gICovCiAgICAvLyBwcml2YXRlIHVwZGF0ZVJld2FyZHMoKTogdm9pZCB7CiAgICAvLyAgIGNvbnN0IGN1cnJlbnRUaW1lID0gR2xvYmFsLmxhdGVzdFRpbWVzdGFtcAogICAgLy8gICBjb25zdCBsYXN0UmV3YXJkID0gdGhpcy5sYXN0UmV3YXJkVGltZS52YWx1ZQogICAgLy8gICBjb25zdCByZXdhcmRQZXJpb2QgPSB0aGlzLnJld2FyZFBlcmlvZC52YWx1ZQogICAgLy8gCiAgICAvLyAgIC8vIENoZWNrIGlmIGEgZnVsbCByZXdhcmQgcGVyaW9kIGhhcyBwYXNzZWQKICAgIC8vICAgaWYgKGN1cnJlbnRUaW1lID49IGxhc3RSZXdhcmQgKyByZXdhcmRQZXJpb2QgJiYgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSA+IDApIHsKICAgIC8vICAgICAvLyBDYWxjdWxhdGUgaG93IG1hbnkgY29tcGxldGUgcGVyaW9kcyBoYXZlIHBhc3NlZAogICAgLy8gICAgIGNvbnN0IHBlcmlvZHNQYXNzZWQ6IHVpbnQ2NCA9IChjdXJyZW50VGltZSAtIGxhc3RSZXdhcmQpIC8gcmV3YXJkUGVyaW9kCiAgICAvLyAKICAgIC8vICAgICAvLyBVcGRhdGUgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUKICAgIC8vICAgICBjb25zdCByZXdhcmRQZXJQZXJpb2QgPSB0aGlzLndlZWtseVJld2FyZHMudmFsdWUKICAgIC8vICAgICBjb25zdCB0b3RhbFJld2FyZHM6IHVpbnQ2NCA9IHJld2FyZFBlclBlcmlvZCAqIHBlcmlvZHNQYXNzZWQKICAgIC8vIAogICAgLy8gICAgIC8vIFNpbXBsZSBkaXZpc2lvbiAtIHJld2FyZHMgcGVyIHRva2VuIHN0YWtlZAogICAgLy8gICAgIGNvbnN0IHRvdGFsU3Rha2VkID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZQogICAgLy8gICAgIGNvbnN0IHJld2FyZFBlclNoYXJlOiB1aW50NjQgPSB0b3RhbFJld2FyZHMgLyB0b3RhbFN0YWtlZAogICAgLy8gCiAgICAvLyAgICAgLy8gVXBkYXRlIGFjY3VtdWxhdGVkIHJld2FyZHMgcGVyIHNoYXJlCiAgICAvLyAgICAgdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSA9IHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUgKyByZXdhcmRQZXJTaGFyZQogICAgLy8gCiAgICAvLyAgICAgLy8gVXBkYXRlIGxhc3QgcmV3YXJkIHRpbWUgdG8gdGhlIG1vc3QgcmVjZW50IGNvbXBsZXRlIHBlcmlvZAogICAgLy8gICAgIHRoaXMubGFzdFJld2FyZFRpbWUudmFsdWUgPSBsYXN0UmV3YXJkICsgKHBlcmlvZHNQYXNzZWQgKiByZXdhcmRQZXJpb2QpCiAgICAvLyAKICAgIC8vICAgICAvLyBEZWR1Y3QgcmV3YXJkcyBmcm9tIHBvb2wKICAgIC8vICAgICB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSB0aGlzLnJld2FyZFBvb2wudmFsdWUgLSB0b3RhbFJld2FyZHMKICAgIC8vICAgfQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIENhbGN1bGF0ZSBwZW5kaW5nIHJld2FyZHMgZm9yIGEgdXNlcgogICAgLy8gICovCiAgICAvLyBwcml2YXRlIGNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzOiBBY2NvdW50KTogdWludDY0IHsKICAgIC8vICAgY29uc3Qgc3Rha2VJbmZvID0gdGhpcy5nZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzKQogICAgLy8gCiAgICAvLyAgIGlmIChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSA9PT0gMCkgewogICAgLy8gICAgIHJldHVybiAwCiAgICAvLyAgIH0KICAgIC8vIAogICAgLy8gICBjb25zdCB1c2VyU3Rha2UgPSBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZQogICAgLy8gICBjb25zdCBhY2NSZXdhcmRzUGVyU2hhcmUgPSB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlCiAgICAvLyAgIGNvbnN0IHVzZXJSZXdhcmREZWJ0ID0gc3Rha2VJbmZvLnJld2FyZERlYnQubmF0aXZlCiAgICAvLyAKICAgIC8vICAgLy8gU2ltcGxlIGNhbGN1bGF0aW9uIHdpdGhvdXQgcHJlY2lzaW9uCiAgICAvLyAgIGNvbnN0IHRvdGFsRWFybmVkOiB1aW50NjQgPSB1c2VyU3Rha2UgKiBhY2NSZXdhcmRzUGVyU2hhcmUKICAgIC8vICAgY29uc3QgcGVuZGluZ1Jld2FyZHM6IHVpbnQ2NCA9IHRvdGFsRWFybmVkID4gdXNlclJld2FyZERlYnQgPyB0b3RhbEVhcm5lZCAtIHVzZXJSZXdhcmREZWJ0IDogMAogICAgLy8gCiAgICAvLyAgIHJldHVybiBwZW5kaW5nUmV3YXJkcwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEhlbHBlciBmdW5jdGlvbiB0byBjb21wb3VuZCByZXdhcmRzIGZvciBhIHVzZXIKICAgIC8vICAqLwogICAgLy8gcHJpdmF0ZSBjb21wb3VuZFJld2FyZHModXNlckFkZHJlc3M6IEFjY291bnQpOiB2b2lkIHsKICAgIC8vICAgY29uc3Qgc3Rha2VJbmZvID0gdGhpcy5nZXRVc2VyU3Rha2VJbmZvKHVzZXJBZGRyZXNzKQogICAgLy8gICBpZiAoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPiAwKSB7CiAgICAvLyAgICAgY29uc3QgcGVuZGluZ1Jld2FyZHMgPSB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gICAgIGlmIChwZW5kaW5nUmV3YXJkcyA+IDApIHsKICAgIC8vICAgICAgIC8vIEFkZCByZXdhcmRzIHRvIHN0YWtlCiAgICAvLyAgICAgICBzdGFrZUluZm8uc3Rha2VkQW1vdW50ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSArIHBlbmRpbmdSZXdhcmRzKQogICAgLy8gICAgICAgc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnRvdGFsUmV3YXJkc0Vhcm5lZC5uYXRpdmUgKyBwZW5kaW5nUmV3YXJkcykKICAgIC8vICAgICAgIHN0YWtlSW5mby5yZXdhcmREZWJ0ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAqIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUpCiAgICAvLyAgICAgICBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMgPSBuZXcgYXJjNC5VaW50TjY0KDApCiAgICAvLyAgICAgICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcywgc3Rha2VJbmZvKQogICAgLy8gCiAgICAvLyAgICAgICAvLyBVcGRhdGUgdG90YWwgc3Rha2VkCiAgICAvLyAgICAgICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSArIHBlbmRpbmdSZXdhcmRzCiAgICAvLyAgICAgfQogICAgLy8gICB9CiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogSW5pdGlhbGl6ZSB0aGUgY29udHJhY3Qgd2l0aCB0aGUgQVNBIHRva2VuIElEIGFuZCBvdGhlciBwYXJhbWV0ZXJzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIGluaXRpYWxpemUoCiAgICAvLyAgIGFzc2V0OiBBc3NldCwKICAgIC8vICAgYWRtaW5BZGRyZXNzOiBBY2NvdW50LAogICAgLy8gICBtaW5pbXVtU3Rha2U6IHVpbnQ2NCwKICAgIC8vICAgd2Vla2x5UmV3YXJkczogdWludDY0LAogICAgLy8gICByZXdhcmRQZXJpb2Q6IHVpbnQ2NCwKICAgIC8vICk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgdGhpcyBpcyBvbmx5IGNhbGxlZCBkdXJpbmcgY29udHJhY3QgY3JlYXRpb24KICAgIC8vICAgYXNzZXJ0KHRoaXMuYXNzZXQudmFsdWUgPT09IEFzc2V0KCksICdBbHJlYWR5IGluaXRpYWxpemVkJykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgb25seSB0aGUgY3JlYXRvciBjYW4gaW5pdGlhbGl6ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gR2xvYmFsLmNyZWF0b3JBZGRyZXNzLCAnT25seSBjcmVhdG9yIGNhbiBpbml0aWFsaXplJykKICAgIC8vIAogICAgLy8gICAvLyBTdG9yZSB0aGUgaW5pdGlhbCBwYXJhbWV0ZXJzCiAgICAvLyAgIHRoaXMuYXNzZXQudmFsdWUgPSBhc3NldAogICAgLy8gICB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZSA9IGFkbWluQWRkcmVzcwogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gMAogICAgLy8gICB0aGlzLmxhc3RSZXdhcmRUaW1lLnZhbHVlID0gR2xvYmFsLmxhdGVzdFRpbWVzdGFtcAogICAgLy8gICB0aGlzLm1pbmltdW1TdGFrZS52YWx1ZSA9IG1pbmltdW1TdGFrZQogICAgLy8gICB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSAwCiAgICAvLyAgIHRoaXMuYWNjdW11bGF0ZWRSZXdhcmRzUGVyU2hhcmUudmFsdWUgPSAwCiAgICAvLyAKICAgIC8vICAgLy8gU2V0IHJld2FyZCBzeXN0ZW0gcGFyYW1ldGVycwogICAgLy8gICB0aGlzLndlZWtseVJld2FyZHMudmFsdWUgPSB3ZWVrbHlSZXdhcmRzCiAgICAvLyAgIHRoaXMucmV3YXJkUGVyaW9kLnZhbHVlID0gcmV3YXJkUGVyaW9kCiAgICAvLyB9CiAgICAvLyAKICAgIC8vIC8qKgogICAgLy8gICogT3B0IHRoZSBjb250cmFjdCBpbnRvIHRoZSBBU0EKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgb3B0SW5Ub0Fzc2V0KCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgb25seSB0aGUgY3JlYXRvciBvciBhZG1pbiBjYW4gb3B0IGluCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBHbG9iYWwuY3JlYXRvckFkZHJlc3MgfHwgVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBjcmVhdG9yIG9yIGFkbWluIGNhbiBvcHQgaW4nKQogICAgLy8gCiAgICAvLyAgIC8vIE9wdCB0aGUgY29udHJhY3QgaW50byB0aGUgQVNBCiAgICAvLyAgIGNvbnN0IGFzc2V0ID0gdGhpcy5hc3NldC52YWx1ZQogICAgLy8gICBpdHhuCiAgICAvLyAgICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgICAgYXNzZXRSZWNlaXZlcjogR2xvYmFsLmN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MsCiAgICAvLyAgICAgICBhc3NldEFtb3VudDogMCwKICAgIC8vICAgICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgICAgfSkKICAgIC8vICAgICAuc3VibWl0KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBTdGFrZSB0b2tlbnMKICAgIC8vICAqIFJlcXVpcmVzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbgogICAgLy8gICogQXV0b21hdGljYWxseSBjbGFpbXMgcGVuZGluZyByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHN0YWtlKCk6IHZvaWQgewogICAgLy8gICAvLyBFbnN1cmUgdGhlIGNvbnRyYWN0IGhhcyBvcHRlZCBpbnRvIHRoZSBBU0EKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGFzc2VydCh0aGlzLmFzc2V0LnZhbHVlICE9PSBBc3NldCgpLCAnQ29udHJhY3Qgbm90IGluaXRpYWxpemVkJykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgdGhpcyBjYWxsIGhhcyBhIGNvbXBhbmlvbiBBU0EgdHJhbnNmZXIgdHJhbnNhY3Rpb24KICAgIC8vICAgYXNzZXJ0KEdsb2JhbC5ncm91cFNpemUgPT09IDIsICdFeHBlY3RlZCAyIHR4bnMgaW4gZ3JvdXAnKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCB0aGUgQVNBIHRyYW5zZmVyIGRldGFpbHMKICAgIC8vICAgY29uc3QgeGZlclR4biA9IGd0eG4uQXNzZXRUcmFuc2ZlclR4bigwKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQXNzZXRUcmFuc2ZlciwgJ1RyYW5zYWN0aW9uIDAgbXVzdCBiZSBhc3NldCB0cmFuc2ZlcicpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0UmVjZWl2ZXIgPT09IEdsb2JhbC5jdXJyZW50QXBwbGljYXRpb25BZGRyZXNzLCAnQXNzZXQgdHJhbnNmZXIgbXVzdCBiZSB0byBjb250cmFjdCcpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLmFzc2V0QW1vdW50ID4gMCwgJ011c3Qgc3Rha2Ugbm9uLXplcm8gYW1vdW50JykKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4ueGZlckFzc2V0ID09PSBhc3NldCwgJ0luY29ycmVjdCBhc3NldCBJRCcpCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBzdGFrZSBhbW91bnQgZnJvbSB0aGUgdHJhbnNhY3Rpb24KICAgIC8vICAgY29uc3Qgc3Rha2VBbW91bnQgPSB4ZmVyVHhuLmFzc2V0QW1vdW50CiAgICAvLyAgIGNvbnN0IG1pbmltdW1TdGFrZSA9IHRoaXMubWluaW11bVN0YWtlLnZhbHVlCiAgICAvLyAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBUeG4uc2VuZGVyCiAgICAvLyAKICAgIC8vICAgLy8gR2V0IHRoZSBjdXJyZW50IHVzZXIgc3Rha2UgaW5mbwogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICAvLyBJZiB0aGlzIGlzIGEgbmV3IHN0YWtlLCBlbnN1cmUgaXQgbWVldHMgbWluaW11bQogICAgLy8gICBpZiAoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPT09IDApIHsKICAgIC8vICAgICBhc3NlcnQoc3Rha2VBbW91bnQgPj0gbWluaW11bVN0YWtlLCAnSW5pdGlhbCBzdGFrZSBiZWxvdyBtaW5pbXVtJykKICAgIC8vICAgICAvLyBTZXQgdGhlIGZpcnN0IHN0YWtlIHRpbWUgKHRoaXMgbmV2ZXIgY2hhbmdlcyBhZnRlciBpbml0aWFsIHN0YWtlKQogICAgLy8gICAgIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZSA9IG5ldyBhcmM0LlVpbnRONjQoR2xvYmFsLmxhdGVzdFRpbWVzdGFtcCkKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBzdGFrZSBpbmZvIHdpdGggbmV3IGFtb3VudAogICAgLy8gICBzdGFrZUluZm8uc3Rha2VkQW1vdW50ID0gbmV3IGFyYzQuVWludE42NChzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSArIHN0YWtlQW1vdW50KQogICAgLy8gICBzdGFrZUluZm8ubGFzdFN0YWtlVGltZSA9IG5ldyBhcmM0LlVpbnRONjQoR2xvYmFsLmxhdGVzdFRpbWVzdGFtcCkKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgcmV3YXJkIGRlYnQKICAgIC8vICAgc3Rha2VJbmZvLnJld2FyZERlYnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlICogdGhpcy5hY2N1bXVsYXRlZFJld2FyZHNQZXJTaGFyZS52YWx1ZSkKICAgIC8vIAogICAgLy8gICAvLyBTdG9yZSB1cGRhdGVkIHN0YWtlIGluZm8KICAgIC8vICAgdGhpcy5zdG9yZVVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcywgc3Rha2VJbmZvKQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBnbG9iYWwgc3RhdGUKICAgIC8vICAgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSA9IHRoaXMudG90YWxTdGFrZWQudmFsdWUgKyBzdGFrZUFtb3VudAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFdpdGhkcmF3IHN0YWtlZCB0b2tlbnMKICAgIC8vICAqIEF1dG9tYXRpY2FsbHkgY2xhaW1zIHBlbmRpbmcgcmV3YXJkcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB3aXRoZHJhdyhhbW91bnQ6IHVpbnQ2NCk6IHZvaWQgewogICAgLy8gICBjb25zdCBzZW5kZXJBZGRyZXNzID0gVHhuLnNlbmRlcgogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8oc2VuZGVyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICAvLyBFbnN1cmUgdXNlciBoYXMgZW5vdWdoIHN0YWtlZAogICAgLy8gICBhc3NlcnQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgPiAwLCAnTm8gc3Rha2UgZm91bmQnKQogICAgLy8gICBhc3NlcnQoYW1vdW50IDw9IHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLCAnV2l0aGRyYXdhbCBhbW91bnQgZXhjZWVkcyBzdGFrZScpCiAgICAvLyAgIGFzc2VydChhbW91bnQgPiAwLCAnV2l0aGRyYXdhbCBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZScpCiAgICAvLyAKICAgIC8vICAgLy8gSWYgd2l0aGRyYXdpbmcgYWxsLCBubyBuZWVkIHRvIGNoZWNrIG1pbmltdW0gcmVtYWluaW5nCiAgICAvLyAgIC8vIElmIHBhcnRpYWwgd2l0aGRyYXdhbCwgZW5zdXJlIHJlbWFpbmluZyBzdGFrZSBtZWV0cyBtaW5pbXVtCiAgICAvLyAgIGlmIChhbW91bnQgPCBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSkgewogICAgLy8gICAgIGNvbnN0IHJlbWFpbmluZ1N0YWtlOiB1aW50NjQgPSBzdGFrZUluZm8uc3Rha2VkQW1vdW50Lm5hdGl2ZSAtIGFtb3VudAogICAgLy8gICAgIGNvbnN0IG1pbmltdW1TdGFrZSA9IHRoaXMubWluaW11bVN0YWtlLnZhbHVlCiAgICAvLyAgICAgYXNzZXJ0KHJlbWFpbmluZ1N0YWtlID49IG1pbmltdW1TdGFrZSwgJ1JlbWFpbmluZyBzdGFrZSB3b3VsZCBiZSBiZWxvdyBtaW5pbXVtJykKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSBzdGFrZSBpbmZvCiAgICAvLyAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQgPSBuZXcgYXJjNC5VaW50TjY0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlIC0gYW1vdW50KQogICAgLy8gCiAgICAvLyAgIC8vIFVwZGF0ZSByZXdhcmQgZGVidAogICAgLy8gICBzdGFrZUluZm8ucmV3YXJkRGVidCA9IG5ldyBhcmM0LlVpbnRONjQoc3Rha2VJbmZvLnN0YWtlZEFtb3VudC5uYXRpdmUgKiB0aGlzLmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlLnZhbHVlKQogICAgLy8gCiAgICAvLyAgIC8vIFN0b3JlIHVwZGF0ZWQgc3Rha2UgaW5mbwogICAgLy8gICB0aGlzLnN0b3JlVXNlclN0YWtlSW5mbyhzZW5kZXJBZGRyZXNzLCBzdGFrZUluZm8pCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIGdsb2JhbCBzdGF0ZQogICAgLy8gICB0aGlzLnRvdGFsU3Rha2VkLnZhbHVlID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZSAtIGFtb3VudAogICAgLy8gCiAgICAvLyAgIC8vIFRyYW5zZmVyIHRva2VucyBiYWNrIHRvIHVzZXIKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGl0eG4KICAgIC8vICAgICAuYXNzZXRUcmFuc2Zlcih7CiAgICAvLyAgICAgICBhc3NldFJlY2VpdmVyOiBzZW5kZXJBZGRyZXNzLAogICAgLy8gICAgICAgYXNzZXRBbW91bnQ6IGFtb3VudCwKICAgIC8vICAgICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgICAgICBmZWU6IDEwMDAsCiAgICAvLyAgICAgfSkKICAgIC8vICAgICAuc3VibWl0KCkKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBBZGQgcmV3YXJkcyB0byB0aGUgcmV3YXJkIHBvb2wKICAgIC8vICAqIE9ubHkgdGhlIGFkbWluIGNhbiBjYWxsIHRoaXMKICAgIC8vICAqIFJlcXVpcmVzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aXRoIHRoZSByZXdhcmRzCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIGFkZFJld2FyZHMoKTogdm9pZCB7CiAgICAvLyAgIC8vIEVuc3VyZSBvbmx5IGFkbWluIGNhbiBhZGQgcmV3YXJkcwogICAgLy8gICBjb25zdCBhZG1pbkFkZHIgPSB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBhZG1pbiBjYW4gYWRkIHJld2FyZHMnKQogICAgLy8gCiAgICAvLyAgIC8vIEVuc3VyZSB0aGlzIGNhbGwgaGFzIGEgY29tcGFuaW9uIEFTQSB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aXRoIHJld2FyZHMKICAgIC8vICAgYXNzZXJ0KEdsb2JhbC5ncm91cFNpemUgPT09IDIsICdFeHBlY3RlZCAyIHR4bnMgaW4gZ3JvdXAnKQogICAgLy8gCiAgICAvLyAgIC8vIEdldCB0aGUgQVNBIHRyYW5zZmVyIGRldGFpbHMKICAgIC8vICAgY29uc3QgYXNzZXQgPSB0aGlzLmFzc2V0LnZhbHVlCiAgICAvLyAgIGNvbnN0IHhmZXJUeG4gPSBndHhuLkFzc2V0VHJhbnNmZXJUeG4oMCkKICAgIC8vICAgYXNzZXJ0KHhmZXJUeG4udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkFzc2V0VHJhbnNmZXIsICdUcmFuc2FjdGlvbiAwIG11c3QgYmUgYXNzZXQgdHJhbnNmZXInKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi5hc3NldFJlY2VpdmVyID09PSBHbG9iYWwuY3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcywgJ0Fzc2V0IHRyYW5zZmVyIG11c3QgYmUgdG8gY29udHJhY3QnKQogICAgLy8gICBhc3NlcnQoeGZlclR4bi5hc3NldEFtb3VudCA+IDAsICdNdXN0IHByb3ZpZGUgbm9uLXplcm8gcmV3YXJkcycpCiAgICAvLyAgIGFzc2VydCh4ZmVyVHhuLnhmZXJBc3NldCA9PT0gYXNzZXQsICdJbmNvcnJlY3QgYXNzZXQgSUQnKQogICAgLy8gCiAgICAvLyAgIC8vIEFkZCByZXdhcmRzIHRvIHRoZSBwb29sCiAgICAvLyAgIHRoaXMucmV3YXJkUG9vbC52YWx1ZSA9IHRoaXMucmV3YXJkUG9vbC52YWx1ZSArIHhmZXJUeG4uYXNzZXRBbW91bnQKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBDYWxjdWxhdGUgY3VycmVudCBBUFkgYmFzZWQgb24gdG90YWwgc3Rha2VkIGFtb3VudAogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRDdXJyZW50QVBZKCk6IHVpbnQ2NCB7CiAgICAvLyAgIGNvbnN0IHRvdGFsU3Rha2VkID0gdGhpcy50b3RhbFN0YWtlZC52YWx1ZQogICAgLy8gCiAgICAvLyAgIGlmICh0b3RhbFN0YWtlZCA9PT0gMCkgewogICAgLy8gICAgIHJldHVybiAwIC8vIFJldHVybiAwIGlmIG5vIHRva2VucyBzdGFrZWQKICAgIC8vICAgfQogICAgLy8gCiAgICAvLyAgIC8vIENhbGN1bGF0ZSBhbm51YWwgcmV3YXJkczogNTIgd2Vla3MgKiB3ZWVrbHlSZXdhcmRzCiAgICAvLyAgIGNvbnN0IGFubnVhbFJld2FyZHM6IHVpbnQ2NCA9IDUyICogdGhpcy53ZWVrbHlSZXdhcmRzLnZhbHVlCiAgICAvLyAKICAgIC8vICAgLy8gQVBZID0gKGFubnVhbFJld2FyZHMgLyB0b3RhbFN0YWtlZCkgKiAxMDAwMCAoaW4gYmFzaXMgcG9pbnRzKQogICAgLy8gICBjb25zdCBhcHk6IHVpbnQ2NCA9IChhbm51YWxSZXdhcmRzICogMTAwKSAvIHRvdGFsU3Rha2VkCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIGFweQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBwZW5kaW5nIHJld2FyZHMgZm9yIGEgc3BlY2lmaWMgdXNlcgogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzczogQWNjb3VudCk6IHVpbnQ2NCB7CiAgICAvLyAgIHJldHVybiB0aGlzLmNhbGN1bGF0ZVBlbmRpbmdSZXdhcmRzKHVzZXJBZGRyZXNzKQogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIFRyaWdnZXIgcmV3YXJkIGRpc3RyaWJ1dGlvbiBtYW51YWxseSAoYWRtaW4gb25seSkKICAgIC8vICAqIFVwZGF0ZXMgYWNjdW11bGF0ZWQgcmV3YXJkcyBwZXIgc2hhcmUgaWYgcGVyaW9kIGhhcyBwYXNzZWQKICAgIC8vICAqIGFuZCBjb21wb3VuZHMgcmV3YXJkcyBmb3IgYWxsIHN0YWtlcnMKICAgIC8vICAqLwogICAgLy8gQGFiaW1ldGhvZCgpCiAgICAvLyBwdWJsaWMgdHJpZ2dlclJld2FyZERpc3RyaWJ1dGlvbigpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIHRyaWdnZXIgZGlzdHJpYnV0aW9uCiAgICAvLyAgIGNvbnN0IGFkbWluQWRkciA9IHRoaXMuYWRtaW5BZGRyZXNzLnZhbHVlCiAgICAvLyAgIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiB0cmlnZ2VyIGRpc3RyaWJ1dGlvbicpCiAgICAvLyAKICAgIC8vICAgLy8gVXBkYXRlIHJld2FyZHMKICAgIC8vICAgdGhpcy51cGRhdGVSZXdhcmRzKCkKICAgIC8vIAogICAgLy8gICAvLyBHZXQgYWxsIHN0YWtlcnMgYW5kIGNvbXBvdW5kIHRoZWlyIHJld2FyZHMKICAgIC8vICAgLy8gTm90ZTogSW4gQWxnb3JhbmQsIHdlIGNhbid0IGl0ZXJhdGUgb3ZlciBhbGwgYm94ZXMgZGlyZWN0bHkKICAgIC8vICAgLy8gSW5zdGVhZCwgd2UnbGwgcmVseSBvbiB0aGUgZmFjdCB0aGF0IHJld2FyZHMgYXJlIGF1dG9tYXRpY2FsbHkKICAgIC8vICAgLy8gY29tcG91bmRlZCB3aGVuIHVzZXJzIGludGVyYWN0IHdpdGggdGhlIGNvbnRyYWN0IChzdGFrZS93aXRoZHJhdykKICAgIC8vICAgLy8gVGhpcyBpcyBtb3JlIGdhcyBlZmZpY2llbnQgYW5kIGZvbGxvd3MgQWxnb3JhbmQncyBkZXNpZ24gcGF0dGVybnMKICAgIC8vIH0KICAgIC8vIAogICAgLy8gLyoqCiAgICAvLyAgKiBVcGRhdGUgdGhlIGFkbWluIGFkZHJlc3MKICAgIC8vICAqIE9ubHkgdGhlIGN1cnJlbnQgYWRtaW4gY2FuIGNhbGwgdGhpcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB1cGRhdGVBZG1pbihuZXdBZG1pbkFkZHJlc3M6IEFjY291bnQpOiB2b2lkIHsKICAgIC8vICAgLy8gRW5zdXJlIG9ubHkgYWRtaW4gY2FuIHVwZGF0ZSBhZG1pbgogICAgLy8gICBjb25zdCBhZG1pbkFkZHIgPSB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZQogICAgLy8gICBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBhZG1pbiBjYW4gdXBkYXRlIGFkbWluJykKICAgIC8vIAogICAgLy8gICAvLyBVcGRhdGUgYWRtaW4gYWRkcmVzcwogICAgLy8gICB0aGlzLmFkbWluQWRkcmVzcy52YWx1ZSA9IG5ld0FkbWluQWRkcmVzcwogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBjdXJyZW50IHN0YWtpbmcgc3RhdGlzdGljcyBmb3IgYSB1c2VyCiAgICAvLyAgKi8KICAgIC8vIEBhYmltZXRob2QoeyByZWFkb25seTogdHJ1ZSB9KQogICAgLy8gcHVibGljIGdldFVzZXJTdGF0cyh1c2VyQWRkcmVzczogQWNjb3VudCk6IEFycmF5PHVpbnQ2ND4gewogICAgLy8gICBjb25zdCBzdGFrZUluZm8gPSB0aGlzLmdldFVzZXJTdGFrZUluZm8odXNlckFkZHJlc3MpCiAgICAvLyAgIGNvbnN0IHBlbmRpbmdSZXdhcmRzID0gdGhpcy5jYWxjdWxhdGVQZW5kaW5nUmV3YXJkcyh1c2VyQWRkcmVzcykKICAgIC8vIAogICAgLy8gICBjb25zdCByZXN1bHQ6IHVpbnQ2NFtdID0gWwogICAgLy8gICAgIHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby5maXJzdFN0YWtlVGltZS5uYXRpdmUsCiAgICAvLyAgICAgc3Rha2VJbmZvLmxhc3RTdGFrZVRpbWUubmF0aXZlLAogICAgLy8gICAgIHN0YWtlSW5mby50b3RhbFJld2FyZHNFYXJuZWQubmF0aXZlLAogICAgLy8gICAgIHBlbmRpbmdSZXdhcmRzLAogICAgLy8gICAgIHN0YWtlSW5mby5yZXdhcmREZWJ0Lm5hdGl2ZSwKICAgIC8vICAgICBzdGFrZUluZm8ucGVuZGluZ1Jld2FyZHMubmF0aXZlLAogICAgLy8gICBdCiAgICAvLyAKICAgIC8vICAgcmV0dXJuIHJlc3VsdAogICAgLy8gfQogICAgLy8gCiAgICAvLyAvKioKICAgIC8vICAqIEdldCBjb250cmFjdCBnbG9iYWwgc3RhdGlzdGljcwogICAgLy8gICovCiAgICAvLyBAYWJpbWV0aG9kKHsgcmVhZG9ubHk6IHRydWUgfSkKICAgIC8vIHB1YmxpYyBnZXRDb250cmFjdFN0YXRzKCk6IEFycmF5PHVpbnQ2ND4gewogICAgLy8gICBjb25zdCBjdXJyZW50QVBZID0gdGhpcy5nZXRDdXJyZW50QVBZKCkKICAgIC8vIAogICAgLy8gICBjb25zdCByZXN1bHQ6IHVpbnQ2NFtdID0gWwogICAgLy8gICAgIHRoaXMuYXNzZXQudmFsdWUuaWQsCiAgICAvLyAgICAgdGhpcy50b3RhbFN0YWtlZC52YWx1ZSwKICAgIC8vICAgICBjdXJyZW50QVBZLAogICAgY29uY2F0CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18zIC8vIDgKICAgIC8KICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICBjb25jYXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDQ0CiAgICAvLyByZXR1cm4gcmVzdWx0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3QuZW1lcmdlbmN5V2l0aGRyYXdSZXdhcmRzKGFtb3VudDogdWludDY0KSAtPiB2b2lkOgplbWVyZ2VuY3lXaXRoZHJhd1Jld2FyZHM6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ1MC00NTEKICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIGVtZXJnZW5jeVdpdGhkcmF3UmV3YXJkcyhhbW91bnQ6IHVpbnQ2NCk6IHZvaWQgewogICAgcHJvdG8gMSAwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU1CiAgICAvLyBwdWJsaWMgYWRtaW5BZGRyZXNzID0gR2xvYmFsU3RhdGU8QWNjb3VudD4oeyBpbml0aWFsVmFsdWU6IEFjY291bnQoKX0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWNfMCAvLyAiYWRtaW5BZGRyZXNzIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDU0CiAgICAvLyBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBhZG1pbiBjYW4gZW1lcmdlbmN5IHdpdGhkcmF3JykKICAgIHR4biBTZW5kZXIKICAgIGRpZyAxCiAgICA9PQogICAgYXNzZXJ0IC8vIE9ubHkgYWRtaW4gY2FuIGVtZXJnZW5jeSB3aXRoZHJhdwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1OQogICAgLy8gcHVibGljIHJld2FyZFBvb2wgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWNfMyAvLyAicmV3YXJkUG9vbCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ1NwogICAgLy8gYXNzZXJ0KHRoaXMucmV3YXJkUG9vbC52YWx1ZSA+PSBhbW91bnQsICdJbnN1ZmZpY2llbnQgcmV3YXJkIHBvb2wnKQogICAgZnJhbWVfZGlnIC0xCiAgICA+PQogICAgYXNzZXJ0IC8vIEluc3VmZmljaWVudCByZXdhcmQgcG9vbAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1OQogICAgLy8gcHVibGljIHJld2FyZFBvb2wgPSBHbG9iYWxTdGF0ZTx1aW50NjQ+KHsgaW5pdGlhbFZhbHVlOiAwIH0pCiAgICBpbnRjXzAgLy8gMAogICAgYnl0ZWNfMyAvLyAicmV3YXJkUG9vbCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ2MAogICAgLy8gdGhpcy5yZXdhcmRQb29sLnZhbHVlID0gdGhpcy5yZXdhcmRQb29sLnZhbHVlIC0gYW1vdW50CiAgICBmcmFtZV9kaWcgLTEKICAgIC0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTkKICAgIC8vIHB1YmxpYyByZXdhcmRQb29sID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgYnl0ZWNfMyAvLyAicmV3YXJkUG9vbCIKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDYwCiAgICAvLyB0aGlzLnJld2FyZFBvb2wudmFsdWUgPSB0aGlzLnJld2FyZFBvb2wudmFsdWUgLSBhbW91bnQKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjU0CiAgICAvLyBwdWJsaWMgYXNzZXQgPSBHbG9iYWxTdGF0ZTxBc3NldD4oeyBpbml0aWFsVmFsdWU6IEFzc2V0KCkgfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18xIC8vICJhc3NldCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ2NC00NzEKICAgIC8vIGl0eG4KICAgIC8vICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgIGFzc2V0UmVjZWl2ZXI6IGFkbWluQWRkciwKICAgIC8vICAgICBhc3NldEFtb3VudDogYW1vdW50LAogICAgLy8gICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgICAgZmVlOiAxMDAwLAogICAgLy8gICB9KQogICAgLy8gICAuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIGl0eG5fZmllbGQgWGZlckFzc2V0CiAgICBmcmFtZV9kaWcgLTEKICAgIGl0eG5fZmllbGQgQXNzZXRBbW91bnQKICAgIGl0eG5fZmllbGQgQXNzZXRSZWNlaXZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0NjQtNDcwCiAgICAvLyBpdHhuCiAgICAvLyAgIC5hc3NldFRyYW5zZmVyKHsKICAgIC8vICAgICBhc3NldFJlY2VpdmVyOiBhZG1pbkFkZHIsCiAgICAvLyAgICAgYXNzZXRBbW91bnQ6IGFtb3VudCwKICAgIC8vICAgICB4ZmVyQXNzZXQ6IGFzc2V0LAogICAgLy8gICAgIGZlZTogMTAwMCwKICAgIC8vICAgfSkKICAgIGludGNfMiAvLyA0CiAgICBpdHhuX2ZpZWxkIFR5cGVFbnVtCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ2OQogICAgLy8gZmVlOiAxMDAwLAogICAgcHVzaGludCAxMDAwIC8vIDEwMDAKICAgIGl0eG5fZmllbGQgRmVlCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ2NC00NzEKICAgIC8vIGl0eG4KICAgIC8vICAgLmFzc2V0VHJhbnNmZXIoewogICAgLy8gICAgIGFzc2V0UmVjZWl2ZXI6IGFkbWluQWRkciwKICAgIC8vICAgICBhc3NldEFtb3VudDogYW1vdW50LAogICAgLy8gICAgIHhmZXJBc3NldDogYXNzZXQsCiAgICAvLyAgICAgZmVlOiAxMDAwLAogICAgLy8gICB9KQogICAgLy8gICAuc3VibWl0KCkKICAgIGl0eG5fc3VibWl0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3QuZGVsZXRlVXNlckJveCh1c2VyQWRkcmVzczogYnl0ZXMpIC0+IHZvaWQ6CmRlbGV0ZVVzZXJCb3g6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ3OC00NzkKICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIGRlbGV0ZVVzZXJCb3godXNlckFkZHJlc3M6IEFjY291bnQpOiB2b2lkIHsKICAgIHByb3RvIDEgMAogICAgaW50Y18wIC8vIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTUKICAgIC8vIHB1YmxpYyBhZG1pbkFkZHJlc3MgPSBHbG9iYWxTdGF0ZTxBY2NvdW50Pih7IGluaXRpYWxWYWx1ZTogQWNjb3VudCgpfSkKICAgIGR1cAogICAgYnl0ZWNfMCAvLyAiYWRtaW5BZGRyZXNzIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBHbG9iYWxTdGF0ZSBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NDg0CiAgICAvLyBhc3NlcnQoVHhuLnNlbmRlciA9PT0gYm94T3duZXIgfHwgVHhuLnNlbmRlciA9PT0gYWRtaW5BZGRyLCAnT25seSBib3ggb3duZXIgb3IgYWRtaW4gY2FuIGRlbGV0ZSBib3gnKQogICAgdHhuIFNlbmRlcgogICAgZnJhbWVfZGlnIC0xCiAgICA9PQogICAgYm56IGRlbGV0ZVVzZXJCb3hfYm9vbF90cnVlQDIKICAgIHR4biBTZW5kZXIKICAgIGZyYW1lX2RpZyAxCiAgICA9PQogICAgYnogZGVsZXRlVXNlckJveF9ib29sX2ZhbHNlQDMKCmRlbGV0ZVVzZXJCb3hfYm9vbF90cnVlQDI6CiAgICBpbnRjXzEgLy8gMQoKZGVsZXRlVXNlckJveF9ib29sX21lcmdlQDQ6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ4NAogICAgLy8gYXNzZXJ0KFR4bi5zZW5kZXIgPT09IGJveE93bmVyIHx8IFR4bi5zZW5kZXIgPT09IGFkbWluQWRkciwgJ09ubHkgYm94IG93bmVyIG9yIGFkbWluIGNhbiBkZWxldGUgYm94JykKICAgIGFzc2VydCAvLyBPbmx5IGJveCBvd25lciBvciBhZG1pbiBjYW4gZGVsZXRlIGJveAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo0ODcKICAgIC8vIGNvbnN0IHN0YWtlSW5mbyA9IHRoaXMuZ2V0VXNlclN0YWtlSW5mbyh1c2VyQWRkcmVzcykKICAgIGZyYW1lX2RpZyAtMQogICAgY2FsbHN1YiBnZXRVc2VyU3Rha2VJbmZvCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ4OAogICAgLy8gYXNzZXJ0KHN0YWtlSW5mby5zdGFrZWRBbW91bnQubmF0aXZlID09PSAwLCAnVXNlciBzdGlsbCBoYXMgYWN0aXZlIHN0YWtlJykKICAgIGludGNfMCAvLyAwCiAgICBleHRyYWN0X3VpbnQ2NAogICAgIQogICAgYXNzZXJ0IC8vIFVzZXIgc3RpbGwgaGFzIGFjdGl2ZSBzdGFrZQogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2NgogICAgLy8gcHVibGljIHN0YWtlcnMgPSBCb3hNYXA8QWNjb3VudCwgVXNlclN0YWtlSW5mbz4oeyBrZXlQcmVmaXg6ICdzdGFrZXJzJyB9KQogICAgYnl0ZWMgMTAgLy8gInN0YWtlcnMiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ5MQogICAgLy8gY29uc3QgdXNlckJveCA9IHRoaXMuc3Rha2Vycyh1c2VyQWRkcmVzcykKICAgIGZyYW1lX2RpZyAtMQogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo2NgogICAgLy8gcHVibGljIHN0YWtlcnMgPSBCb3hNYXA8QWNjb3VudCwgVXNlclN0YWtlSW5mbz4oeyBrZXlQcmVmaXg6ICdzdGFrZXJzJyB9KQogICAgY29uY2F0CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ5MQogICAgLy8gY29uc3QgdXNlckJveCA9IHRoaXMuc3Rha2Vycyh1c2VyQWRkcmVzcykKICAgIGR1cAogICAgZnJhbWVfYnVyeSAwCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ5MgogICAgLy8gaWYgKHVzZXJCb3guZXhpc3RzKSB7CiAgICBib3hfbGVuCiAgICBidXJ5IDEKICAgIGJ6IGRlbGV0ZVVzZXJCb3hfYWZ0ZXJfaWZfZWxzZUA2CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjQ5MwogICAgLy8gdXNlckJveC5kZWxldGUoKQogICAgZnJhbWVfZGlnIDAKICAgIGJveF9kZWwKICAgIHBvcAoKZGVsZXRlVXNlckJveF9hZnRlcl9pZl9lbHNlQDY6CiAgICByZXRzdWIKCmRlbGV0ZVVzZXJCb3hfYm9vbF9mYWxzZUAzOgogICAgaW50Y18wIC8vIDAKICAgIGIgZGVsZXRlVXNlckJveF9ib29sX21lcmdlQDQKCgovLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjpBU0FTdGFraW5nQ29udHJhY3QudXBkYXRlV2Vla2x5UmV3YXJkcyhuZXdXZWVrbHlSZXdhcmRzOiB1aW50NjQpIC0+IHZvaWQ6CnVwZGF0ZVdlZWtseVJld2FyZHM6CiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUwMC01MDEKICAgIC8vIEBhYmltZXRob2QoKQogICAgLy8gcHVibGljIHVwZGF0ZVdlZWtseVJld2FyZHMobmV3V2Vla2x5UmV3YXJkczogdWludDY0KTogdm9pZCB7CiAgICBwcm90byAxIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTUKICAgIC8vIHB1YmxpYyBhZG1pbkFkZHJlc3MgPSBHbG9iYWxTdGF0ZTxBY2NvdW50Pih7IGluaXRpYWxWYWx1ZTogQWNjb3VudCgpfSkKICAgIGludGNfMCAvLyAwCiAgICBieXRlY18wIC8vICJhZG1pbkFkZHJlc3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIEdsb2JhbFN0YXRlIGV4aXN0cwogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1MDQKICAgIC8vIGFzc2VydChUeG4uc2VuZGVyID09PSBhZG1pbkFkZHIsICdPbmx5IGFkbWluIGNhbiB1cGRhdGUgd2Vla2x5IHJld2FyZHMnKQogICAgdHhuIFNlbmRlcgogICAgPT0KICAgIGFzc2VydCAvLyBPbmx5IGFkbWluIGNhbiB1cGRhdGUgd2Vla2x5IHJld2FyZHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTA3CiAgICAvLyB0aGlzLnVwZGF0ZVJld2FyZHMoKQogICAgY2FsbHN1YiB1cGRhdGVSZXdhcmRzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjYzCiAgICAvLyBwdWJsaWMgd2Vla2x5UmV3YXJkcyA9IEdsb2JhbFN0YXRlPHVpbnQ2ND4oeyBpbml0aWFsVmFsdWU6IDAgfSkKICAgIGJ5dGVjIDcgLy8gIndlZWtseVJld2FyZHMiCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUxMAogICAgLy8gdGhpcy53ZWVrbHlSZXdhcmRzLnZhbHVlID0gbmV3V2Vla2x5UmV3YXJkcwogICAgZnJhbWVfZGlnIC0xCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo6QVNBU3Rha2luZ0NvbnRyYWN0LnVwZGF0ZVJld2FyZFBlcmlvZChuZXdSZXdhcmRQZXJpb2Q6IHVpbnQ2NCkgLT4gdm9pZDoKdXBkYXRlUmV3YXJkUGVyaW9kOgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1MTYtNTE3CiAgICAvLyBAYWJpbWV0aG9kKCkKICAgIC8vIHB1YmxpYyB1cGRhdGVSZXdhcmRQZXJpb2QobmV3UmV3YXJkUGVyaW9kOiB1aW50NjQpOiB2b2lkIHsKICAgIHByb3RvIDEgMAogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1NQogICAgLy8gcHVibGljIGFkbWluQWRkcmVzcyA9IEdsb2JhbFN0YXRlPEFjY291bnQ+KHsgaW5pdGlhbFZhbHVlOiBBY2NvdW50KCl9KQogICAgaW50Y18wIC8vIDAKICAgIGJ5dGVjXzAgLy8gImFkbWluQWRkcmVzcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgR2xvYmFsU3RhdGUgZXhpc3RzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjUyMAogICAgLy8gYXNzZXJ0KFR4bi5zZW5kZXIgPT09IGFkbWluQWRkciwgJ09ubHkgYWRtaW4gY2FuIHVwZGF0ZSByZXdhcmQgcGVyaW9kJykKICAgIHR4biBTZW5kZXIKICAgID09CiAgICBhc3NlcnQgLy8gT25seSBhZG1pbiBjYW4gdXBkYXRlIHJld2FyZCBwZXJpb2QKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9zdGFraW5nL2NvbnRyYWN0LmFsZ28udHM6NTIzCiAgICAvLyB0aGlzLnVwZGF0ZVJld2FyZHMoKQogICAgY2FsbHN1YiB1cGRhdGVSZXdhcmRzCiAgICAvLyBzbWFydF9jb250cmFjdHMvc3Rha2luZy9jb250cmFjdC5hbGdvLnRzOjY0CiAgICAvLyBwdWJsaWMgcmV3YXJkUGVyaW9kID0gR2xvYmFsU3RhdGU8dWludDY0Pih7IGluaXRpYWxWYWx1ZTogMCB9KQogICAgYnl0ZWMgOCAvLyAicmV3YXJkUGVyaW9kIgogICAgLy8gc21hcnRfY29udHJhY3RzL3N0YWtpbmcvY29udHJhY3QuYWxnby50czo1MjYKICAgIC8vIHRoaXMucmV3YXJkUGVyaW9kLnZhbHVlID0gbmV3UmV3YXJkUGVyaW9kCiAgICBmcmFtZV9kaWcgLTEKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCiNwcmFnbWEgdHlwZXRyYWNrIGZhbHNlCgovLyBAYWxnb3JhbmRmb3VuZGF0aW9uL2FsZ29yYW5kLXR5cGVzY3JpcHQvYmFzZS1jb250cmFjdC5kLnRzOjpCYXNlQ29udHJhY3QuY2xlYXJTdGF0ZVByb2dyYW0oKSAtPiB1aW50NjQ6Cm1haW46CiAgICBwdXNoaW50IDEgLy8gMQogICAgcmV0dXJuCg==" }, "byteCode": { "approval": "CiAEAAEECCYLDGFkbWluQWRkcmVzcwVhc3NldAt0b3RhbFN0YWtlZApyZXdhcmRQb29sGmFjY3VtdWxhdGVkUmV3YXJkc1BlclNoYXJlDmxhc3RSZXdhcmRUaW1lDG1pbmltdW1TdGFrZQ13ZWVrbHlSZXdhcmRzDHJld2FyZFBlcmlvZAQVH3x1B3N0YWtlcnMxGEAAISkiZygyA2cqImcnBSJnJwYiZysiZycEImcnByJnJwgiZzEbQQG3ghEEZeFpTwQ8O+VeBGZ8XTAEn/0+UwQIkL1YBCHx3f8Es7cBRgS/i3ZtBBg4OOkEIbGwIgSCqx7EBBV2awkEv+MVZATOljsdBNyaKgUEHitSqwQbh0rWNhoAjhEBIgEMAOgA3ADQAMAAtACiAIoAfgBsAFUARAA0ACIAEgACIkMxGRREMRhENhoBF4gFHCNDMRkURDEYRDYaAReIBPgjQzEZFEQxGEQ2GgEXwByIBKwjQzEZFEQxGEQ2GgEXiARmI0MxGRREMRhEiAQOJwlMULAjQzEZFEQxGEQ2GgEXwByIA6knCUxQsCNDMRkURDEYRDYaARfAHIgDgiNDMRkURDEYRIgDaiNDMRkURDEYRDYaARfAHIgDTxYnCUxQsCNDMRkURDEYRIgDHBYnCUxQsCNDMRkURDEYRIgC0iNDMRkURDEYRDYaAReIAlcjQzEZFEQxGESIAcsjQzEZFEQxGESIAYsjQzEZFEQxGEQ2GgEXwDA2GgIXwBw2GgMXNhoEFzYaBReIATEjQzEZFEQxGEQ2GgEXwBw2GgKIAG5II0MxGRREMRhENhoBF8AciAASJwlMULAjQzEZQP7CMRgURCNDigEBJwqL/1BJvUUBQQAGiwC+REyJgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMiYoCAScKi/5Qi/+/i/+JigAAMgdJIicFZUxJTgJOA0QiJwhlTElOAk4ERAgPQQBDIiplREEAPIsAiwFJTgIJiwJJTgIKIicHZURLAQsiKmVESwFMCiInBGVECCcETGdMTwILTwIIJwVMZyIrZURMCStMZ4mKAQGAAEmL/4j/OUkiW0lAAAQijACJIicEZUSLAoEgW0mMAYsDTwILSYwADEEACIsAiwEJjACJIkL/+YoFACIpZUQURDEAMgkSRCmL+2coi/xnKiJnJwUyB2cnBov9ZysiZycEImcnB4v+ZycIi/9niYoAACIoZUQxADIJEkAACDEAiwASQQAZI0QiKWVEsTIKTLIRIrISshQkshAisgGziSJC/+SKAAAiKWVEIillREQyBIECEkQiOBBJJBJEJBJEIjgUMgoSRCI4EklOAkQiOBESRCInBmVEMQBJiP5lRwIiW0AAEIsAiwEPRDIHFosDTFwIjASLBEkiW4sASU4DCBZcADIHFlwQSSJbIicEZUQLFlwgiwJMiP5ySCIqZUQIKkxniYoBADEASYj+FkkiW0cCRIv/SwEORIv/RIv/DUEADIsCi/8JIicGZUQPRIsCi/8JFosBTFwASSJbIicEZUQLFlwgiwBJTwKI/h9IIiplRIv/CSpMZyIpZUSxshGL/7ISshQkshCB6AeyAbOJIihlRDEAEkQyBIECEkQiKWVEIjgQSSQSRCQSRCI4FDIKEkQiOBJJRCI4EU8CEkQiK2VECCtMZ4mKAAEiKmVMSU8CREAAAyJMiSInB2VEgTQLgWQLiwAKTImKAQGL/4j+D4kiKGVEMQASRIj9nomKAQAiKGVEMQASRCiL/2eJigEBi/+I/S6L/4j95UsBIltLAiVbSwOBEFtLBIEYW0sFgSBbTwaBKFtPBRZPBRZQTwQWUE8DFlBPAxZQTwIWUEwWUEkVJQoWVwYCTFCJiP9pIillRCIqZUQiJwVlRCInCGVEIicGZUQiK2VEIicEZURPBhZPBhZQTwYWUE8FFlBPBBZQTwMWUE8CFlBMFlBJFSUKFlcGAkxQiYoBACIoZUQxAEsBEkQiK2VEi/8PRCIrZUSL/wkrTGciKWVEsbIRi/+yErIUJLIQgegHsgGziYoBACJJKGVEMQCL/xJAAAgxAIsBEkEAHiNEi/+I/EciWxREJwqL/1BJjAC9RQFBAASLALxIiSJC/9+KAQAiKGVEMQASRIj8dScHi/9niYoBACIoZUQxABJEiPxhJwiL/2eJ", "clear": "CoEBQw==" }, "compilerInfo": { "compiler": "puya", "compilerVersion": { "major": 4, "minor": 7, "patch": 0 } }, "events": [], "templateVariables": {} }