LyoKICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZSBvciBtb3JlCiAqIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCiAqIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlIHRvIFlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wCiAqICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqCiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCiAqLwpwYWNrYWdlIG9yZy5hcGFjaGUuc2VydmljZW1peC5tYXZlbi5wbHVnaW4uamJpOwoKaW1wb3J0IGphdmEuaW8uRmlsZTsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKCmltcG9ydCBqYXZheC54bWwubmFtZXNwYWNlLlFOYW1lOwppbXBvcnQgamF2YXgueG1sLnBhcnNlcnMuRG9jdW1lbnRCdWlsZGVyOwppbXBvcnQgamF2YXgueG1sLnBhcnNlcnMuRG9jdW1lbnRCdWlsZGVyRmFjdG9yeTsKCmltcG9ydCBvcmcudzNjLmRvbS5Eb2N1bWVudDsKaW1wb3J0IG9yZy53M2MuZG9tLkVsZW1lbnQ7CmltcG9ydCBvcmcudzNjLmRvbS5Ob2RlOwppbXBvcnQgb3JnLnczYy5kb20uTm9kZUxpc3Q7CgppbXBvcnQganVuaXQuZnJhbWV3b3JrLlRlc3RDYXNlOwoKaW1wb3J0IG9yZy5hcGFjaGUuc2VydmljZW1peC5jb21tb24ucGFja2FnaW5nLkNvbnN1bWVzOwppbXBvcnQgb3JnLmFwYWNoZS5zZXJ2aWNlbWl4LmNvbW1vbi5wYWNrYWdpbmcuUHJvdmlkZXM7CgpwdWJsaWMgY2xhc3MgSmJpU2VydmljZVVuaXREZXNjcmlwdG9yV3JpdGVyVGVzdCBleHRlbmRzIFRlc3RDYXNlIHsKCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgRU5DT0RJTkdfVVRGOCA9ICJVVEYtOCI7CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIEVOQ09ESU5HX1VURjE2ID0gIlVURi0xNiI7CgogICAgLy9wcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgRU5DT0RJTkdfSVNPODg1OTEgPSAiSVNPLTg4NTktMSI7CgogICAgLy9wcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgRU5DT0RJTkdfSVNPODg1OTIgPSAiSVNPLTg4NTktMiI7CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIEpCSV9OQU1FU1BBQ0UgPSAiaHR0cDovL2phdmEuc3VuLmNvbS94bWwvbnMvamJpIjsKCiAgICAvLyBUT0RPOiBob3cgdG8gZmV0Y2ggdGhlIGJ1aWxkIGRpcmVjdG9yeSAoJy4vdGFyZ2V0JykgZnJvbSBNYXZlbiBwcm9wZXJ0eT8KICAgIHByaXZhdGUgU3RyaW5nIGdlbmVyYXRlZERlc2NyaXB0b3JMb2NhdGlvbiA9ICIuL3RhcmdldC90ZXN0LW91dHB1dHMiOwoKICAgIHByaXZhdGUgRmlsZSBvdXRwdXREaXI7CgogICAgcHJvdGVjdGVkIHZvaWQgc2V0VXAoKSB0aHJvd3MgRXhjZXB0aW9uIHsKICAgICAgICBzdXBlci5zZXRVcCgpOwoKICAgICAgICB0aGlzLm91dHB1dERpciA9IG5ldyBGaWxlKGdlbmVyYXRlZERlc2NyaXB0b3JMb2NhdGlvbik7CiAgICAgICAgaWYgKCF0aGlzLm91dHB1dERpci5leGlzdHMoKSkgewogICAgICAgICAgICB0aGlzLm91dHB1dERpci5ta2RpcnMoKTsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIHZvaWQgdGVzdFVURjhFbmNvZGluZ1dyaXRlKCkgdGhyb3dzIEV4Y2VwdGlvbiB7CiAgICAgICAgRmlsZSBkZXNjcmlwdG9yID0gbmV3IEZpbGUob3V0cHV0RGlyLCAiamJpLXN1LVVURjgueG1sIik7CgogICAgICAgIFN0cmluZyB4bWxFbmNvZGluZyA9IEVOQ09ESU5HX1VURjg7CiAgICAgICAgd3JpdGVEZXNjcmlwdG9yKGRlc2NyaXB0b3IsIHhtbEVuY29kaW5nKTsKICAgICAgICB2ZXJpZnlEZXNjcmlwdG9yKGRlc2NyaXB0b3IsIHhtbEVuY29kaW5nKTsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCB0ZXN0VVRGMTZFbmNvZGluZ1dyaXRlKCkgdGhyb3dzIEV4Y2VwdGlvbiB7CiAgICAgICAgRmlsZSBkZXNjcmlwdG9yID0gbmV3IEZpbGUob3V0cHV0RGlyLCAiamJpLXN1LVVURjE2LnhtbCIpOwoKICAgICAgICBTdHJpbmcgeG1sRW5jb2RpbmcgPSBFTkNPRElOR19VVEYxNjsKICAgICAgICB3cml0ZURlc2NyaXB0b3IoZGVzY3JpcHRvciwgeG1sRW5jb2RpbmcpOwogICAgICAgIHZlcmlmeURlc2NyaXB0b3IoZGVzY3JpcHRvciwgeG1sRW5jb2RpbmcpOwogICAgfQoKICAgIC8qCiAgICAgKiBwdWJsaWMgdm9pZCB0ZXN0SVNPODg1OTFFbmNvZGluZ1dyaXRlKCkgdGhyb3dzIEV4Y2VwdGlvbiB7IEZpbGUKICAgICAqIGRlc2NyaXB0b3IgPSBuZXcgRmlsZShvdXRwdXREaXIsICJqYmktc3UtSVNPODg1OTEueG1sIik7CiAgICAgKiAKICAgICAqIFN0cmluZyB4bWxFbmNvZGluZyA9IEVOQ09ESU5HX0lTTzg4NTkxOyB3cml0ZURlc2NyaXB0b3IoZGVzY3JpcHRvciwKICAgICAqIHhtbEVuY29kaW5nKTsgdmVyaWZ5RGVzY3JpcHRvcihkZXNjcmlwdG9yLCB4bWxFbmNvZGluZyk7IH0KICAgICAqIAogICAgICogcHVibGljIHZvaWQgdGVzdElTTzg4NTkyRW5jb2RpbmdXcml0ZSgpIHRocm93cyBFeGNlcHRpb24geyBGaWxlCiAgICAgKiBkZXNjcmlwdG9yID0gbmV3IEZpbGUob3V0cHV0RGlyLCAiamJpLXN1LUlTTzg4NTkyLnhtbCIpOwogICAgICogCiAgICAgKiBTdHJpbmcgeG1sRW5jb2RpbmcgPSBFTkNPRElOR19JU084ODU5Mjsgd3JpdGVEZXNjcmlwdG9yKGRlc2NyaXB0b3IsCiAgICAgKiB4bWxFbmNvZGluZyk7IHZlcmlmeURlc2NyaXB0b3IoZGVzY3JpcHRvciwgeG1sRW5jb2RpbmcpOyB9CiAgICAgKi8KCiAgICBwcml2YXRlIHZvaWQgd3JpdGVEZXNjcmlwdG9yKEZpbGUgZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0cmluZyBlbmNvZGluZykgdGhyb3dzIEpiaVBsdWdpbkV4Y2VwdGlvbiB7CiAgICAgICAgTGlzdCBjb25zdW1lcyA9IG5ldyBBcnJheUxpc3QoKTsKICAgICAgICBMaXN0IHByb3ZpZGVzID0gbmV3IEFycmF5TGlzdCgpOwoKICAgICAgICBRTmFtZSBzZXJ2aWNlTmFtZSA9IG5ldyBRTmFtZSgiaHR0cDovL3Rlc3QuY29tL2VuY29kaW5nIiwgImFiY+Xk9iIpOwoKICAgICAgICBDb25zdW1lcyBuZXdDb25zdW1lcyA9IG5ldyBDb25zdW1lcygpOwogICAgICAgIG5ld0NvbnN1bWVzLnNldFNlcnZpY2VOYW1lKHNlcnZpY2VOYW1lKTsKICAgICAgICBuZXdDb25zdW1lcy5zZXRFbmRwb2ludE5hbWUoImNvbnN1bWVy5eT2Iik7CiAgICAgICAgY29uc3VtZXMuYWRkKG5ld0NvbnN1bWVzKTsKCiAgICAgICAgUHJvdmlkZXMgbmV3UHJvdmlkZXMgPSBuZXcgUHJvdmlkZXMoKTsKICAgICAgICBuZXdQcm92aWRlcy5zZXRTZXJ2aWNlTmFtZShzZXJ2aWNlTmFtZSk7CiAgICAgICAgbmV3UHJvdmlkZXMuc2V0RW5kcG9pbnROYW1lKCJwcm92aWRlcuXk9iIpOwogICAgICAgIHByb3ZpZGVzLmFkZChuZXdQcm92aWRlcyk7CgogICAgICAgIEpiaVNlcnZpY2VVbml0RGVzY3JpcHRvcldyaXRlciB3cml0ZXIgPSBuZXcgSmJpU2VydmljZVVuaXREZXNjcmlwdG9yV3JpdGVyKAogICAgICAgICAgICAgICAgZW5jb2RpbmcpOwogICAgICAgIHdyaXRlci53cml0ZShkZXNjcmlwdG9yLCBmYWxzZSwgIm5hbWUiLCAiZGVzY3JpcHRpb24iLCBuZXcgQXJyYXlMaXN0KCksCiAgICAgICAgICAgICAgICBjb25zdW1lcywgcHJvdmlkZXMpOwogICAgfQoKICAgIHByaXZhdGUgdm9pZCB2ZXJpZnlEZXNjcmlwdG9yKEZpbGUgZGVzY3JpcHRvciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHJpbmcgZXhwZWN0ZWRYbWxFbmNvZGluZykgdGhyb3dzIEV4Y2VwdGlvbiB7CiAgICAgICAgRG9jdW1lbnQgZG9jID0gZ2V0RG9jdW1lbnQoZGVzY3JpcHRvcik7CiAgICAgICAgYXNzZXJ0RXF1YWxzKGRvYy5nZXRYbWxFbmNvZGluZygpLCBleHBlY3RlZFhtbEVuY29kaW5nKTsKCiAgICAgICAgRWxlbWVudCBzZXJ2aWNlRWxlbWVudCA9IGdldFNlcnZpY2VzRWxlbWVudChkb2MpOwoKICAgICAgICBMaXN0IGNvbnN1bWVzID0gZ2V0Q29uc3VtZXMoc2VydmljZUVsZW1lbnQpOwogICAgICAgIENvbnN1bWVzIGNvbiA9IChDb25zdW1lcykgY29uc3VtZXMuZ2V0KDApOwogICAgICAgIGFzc2VydEVxdWFscyhjb24uZ2V0U2VydmljZU5hbWUoKS5nZXRMb2NhbFBhcnQoKSwgImFiY+Xk9iIpOwogICAgICAgIGFzc2VydEVxdWFscyhjb24uZ2V0RW5kcG9pbnROYW1lKCksICJjb25zdW1lcuXk9iIpOwoKICAgICAgICBMaXN0IHByb3ZpZGVzID0gZ2V0UHJvdmlkZXMoc2VydmljZUVsZW1lbnQpOwogICAgICAgIFByb3ZpZGVzIHByb3YgPSAoUHJvdmlkZXMpIHByb3ZpZGVzLmdldCgwKTsKICAgICAgICBhc3NlcnRFcXVhbHMocHJvdi5nZXRTZXJ2aWNlTmFtZSgpLmdldExvY2FsUGFydCgpLCAiYWJj5eT2Iik7CiAgICAgICAgYXNzZXJ0RXF1YWxzKHByb3YuZ2V0RW5kcG9pbnROYW1lKCksICJwcm92aWRlcuXk9iIpOwogICAgfQoKICAgIHByaXZhdGUgRG9jdW1lbnQgZ2V0RG9jdW1lbnQoRmlsZSBqYmlTZXJ2aWNlc0ZpbGUpIHRocm93cyBFeGNlcHRpb24gewogICAgICAgIERvY3VtZW50QnVpbGRlckZhY3RvcnkgZGJmID0gRG9jdW1lbnRCdWlsZGVyRmFjdG9yeS5uZXdJbnN0YW5jZSgpOwogICAgICAgIGRiZi5zZXROYW1lc3BhY2VBd2FyZSh0cnVlKTsKICAgICAgICBEb2N1bWVudEJ1aWxkZXIgZGIgPSBkYmYubmV3RG9jdW1lbnRCdWlsZGVyKCk7CiAgICAgICAgRG9jdW1lbnQgZG9jID0gZGIucGFyc2UoamJpU2VydmljZXNGaWxlKTsKCiAgICAgICAgcmV0dXJuIGRvYzsKICAgIH0KCiAgICBwcml2YXRlIEVsZW1lbnQgZ2V0U2VydmljZXNFbGVtZW50KERvY3VtZW50IGRvYykgdGhyb3dzIEV4Y2VwdGlvbiB7CiAgICAgICAgTm9kZSBqYmlOb2RlID0gZG9jLmdldEZpcnN0Q2hpbGQoKTsKICAgICAgICBhc3NlcnRUcnVlKFhtbERlc2NyaXB0b3JIZWxwZXIuaXNFbGVtZW50KGpiaU5vZGUsIEpCSV9OQU1FU1BBQ0UsICJqYmkiKSk7CiAgICAgICAgTm9kZSB0bXBOb2RlID0gamJpTm9kZS5nZXRGaXJzdENoaWxkKCk7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgICAgYXNzZXJ0Tm90TnVsbCh0bXBOb2RlKTsKICAgICAgICAgICAgaWYgKFhtbERlc2NyaXB0b3JIZWxwZXIuaXNFbGVtZW50KHRtcE5vZGUsIEpCSV9OQU1FU1BBQ0UsCiAgICAgICAgICAgICAgICAgICAgInNlcnZpY2VzIikpIHsKICAgICAgICAgICAgICAgIHJldHVybiAoRWxlbWVudCkgdG1wTm9kZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRtcE5vZGUgPSB0bXBOb2RlLmdldE5leHRTaWJsaW5nKCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBMaXN0IGdldENvbnN1bWVzKEVsZW1lbnQgc2VydmljZXNFbGVtZW50KSB0aHJvd3MgRXhjZXB0aW9uIHsKICAgICAgICBMaXN0IGNvbnN1bWVzID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgIE5vZGVMaXN0IGNoaWxkcmVuID0gc2VydmljZXNFbGVtZW50LmdldENoaWxkTm9kZXMoKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaWxkcmVuLmdldExlbmd0aCgpOyBpKyspIHsKICAgICAgICAgICAgaWYgKGNoaWxkcmVuLml0ZW0oaSkgaW5zdGFuY2VvZiBFbGVtZW50KSB7CiAgICAgICAgICAgICAgICBFbGVtZW50IGNoaWxkRWxlbWVudCA9IChFbGVtZW50KSBjaGlsZHJlbi5pdGVtKGkpOwogICAgICAgICAgICAgICAgaWYgKFhtbERlc2NyaXB0b3JIZWxwZXIuaXNFbGVtZW50KGNoaWxkRWxlbWVudCwgSkJJX05BTUVTUEFDRSwKICAgICAgICAgICAgICAgICAgICAgICAgImNvbnN1bWVzIikpIHsKICAgICAgICAgICAgICAgICAgICBDb25zdW1lcyBuZXdDb25zdW1lcyA9IG5ldyBDb25zdW1lcygpOwogICAgICAgICAgICAgICAgICAgIG5ld0NvbnN1bWVzLnNldEVuZHBvaW50TmFtZShYbWxEZXNjcmlwdG9ySGVscGVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZ2V0RW5kcG9pbnROYW1lKGNoaWxkRWxlbWVudCkpOwogICAgICAgICAgICAgICAgICAgIG5ld0NvbnN1bWVzLnNldEludGVyZmFjZU5hbWUoWG1sRGVzY3JpcHRvckhlbHBlcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgLmdldEludGVyZmFjZU5hbWUoY2hpbGRFbGVtZW50KSk7CiAgICAgICAgICAgICAgICAgICAgbmV3Q29uc3VtZXMuc2V0U2VydmljZU5hbWUoWG1sRGVzY3JpcHRvckhlbHBlcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgLmdldFNlcnZpY2VOYW1lKGNoaWxkRWxlbWVudCkpOwogICAgICAgICAgICAgICAgICAgIGNvbnN1bWVzLmFkZChuZXdDb25zdW1lcyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiBjb25zdW1lczsKICAgIH0KCiAgICBwcml2YXRlIExpc3QgZ2V0UHJvdmlkZXMoRWxlbWVudCBzZXJ2aWNlc0VsZW1lbnQpIHRocm93cyBFeGNlcHRpb24gewogICAgICAgIExpc3QgcHJvdmlkZXMgPSBuZXcgQXJyYXlMaXN0KCk7CiAgICAgICAgTm9kZUxpc3QgY2hpbGRyZW4gPSBzZXJ2aWNlc0VsZW1lbnQuZ2V0Q2hpbGROb2RlcygpOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4uZ2V0TGVuZ3RoKCk7IGkrKykgewogICAgICAgICAgICBpZiAoY2hpbGRyZW4uaXRlbShpKSBpbnN0YW5jZW9mIEVsZW1lbnQpIHsKICAgICAgICAgICAgICAgIEVsZW1lbnQgY2hpbGRFbGVtZW50ID0gKEVsZW1lbnQpIGNoaWxkcmVuLml0ZW0oaSk7CiAgICAgICAgICAgICAgICBpZiAoWG1sRGVzY3JpcHRvckhlbHBlci5pc0VsZW1lbnQoY2hpbGRFbGVtZW50LCBKQklfTkFNRVNQQUNFLAogICAgICAgICAgICAgICAgICAgICAgICAicHJvdmlkZXMiKSkgewogICAgICAgICAgICAgICAgICAgIFByb3ZpZGVzIG5ld1Byb3ZpZGVzID0gbmV3IFByb3ZpZGVzKCk7CiAgICAgICAgICAgICAgICAgICAgbmV3UHJvdmlkZXMuc2V0RW5kcG9pbnROYW1lKFhtbERlc2NyaXB0b3JIZWxwZXIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5nZXRFbmRwb2ludE5hbWUoY2hpbGRFbGVtZW50KSk7CiAgICAgICAgICAgICAgICAgICAgbmV3UHJvdmlkZXMuc2V0SW50ZXJmYWNlTmFtZShYbWxEZXNjcmlwdG9ySGVscGVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZ2V0SW50ZXJmYWNlTmFtZShjaGlsZEVsZW1lbnQpKTsKICAgICAgICAgICAgICAgICAgICBuZXdQcm92aWRlcy5zZXRTZXJ2aWNlTmFtZShYbWxEZXNjcmlwdG9ySGVscGVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZ2V0U2VydmljZU5hbWUoY2hpbGRFbGVtZW50KSk7CiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXMuYWRkKG5ld1Byb3ZpZGVzKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHByb3ZpZGVzOwogICAgfQp9Cg==