LyoKLyoKICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZSBvciBtb3JlCiAqIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCiAqIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlIHRvIFlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wCiAqICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqCiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCiAqLwpwYWNrYWdlIG9yZy5hcGFjaGUuY29tbW9ucy50ZXh0Lm5hbWVzOwoKaW1wb3J0IGphdmEudXRpbC5BcnJheXM7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5PYmplY3RzOwoKaW1wb3J0IG9yZy5hcGFjaGUuY29tbW9ucy5sYW5nMy5TdHJpbmdVdGlsczsKCi8qKgogKiBBIHBhcnNlciBjYXBhYmxlIG9mIHBhcnNpbmcgbmFtZSBwYXJ0cyBvdXQgb2YgYSBzaW5nbGUgc3RyaW5nLgogKgogKiA8aDM+UGFyc2luZyBleGFtcGxlczwvaDM+CiAqIAogKiA8cD5UaGUgY29kZSB3b3JrcyBieSBiYXNpY2FsbHkgYXBwbHlpbmcgc2V2ZXJhbCBSZWdleGVzIGluIGEgY2VydGFpbiBvcmRlcgogKiBhbmQgcmVtb3ZpbmcgKGNob3BwaW5nKSB0b2tlbnMgb2ZmIHRoZSBvcmlnaW5hbCBzdHJpbmcuIFRoZSBwYXJzZXIgY3JlYXRlcwogKiBhIHtAbGluayBOYW1lfSBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBwYXJzZSByZXN1bHQuIE5vdGUgdGhhdCBwYXNzaW5nIG51bGwKICogdG8gdGhlIHtAbGluayAjcGFyc2UoU3RyaW5nKX0gbWV0aG9kIHdpbGwgcmVzdWx0IGluIGFuIGV4Y2VwdGlvbi48L3A+CiAqCiAqIDx0YWJsZT4KICogIDx0cj4KICogICA8dGg+aW5wdXQ8L3RoPgogKiAgIDx0aD5MZWFkaW5nIGluaXRpYWw8L3RoPgogKiAgIDx0aD5GaXJzdCBuYW1lPC90aD4KICogICA8dGg+TmljayBuYW1lPC90aD4KICogICA8dGg+TWlkZGxlIG5hbWU8L3RoPgogKiAgIDx0aD5MYXN0IE5hbWU8L3RoPgogKiAgIDx0aD5TdWZmaXg8L3RoPgogKiAgPC90cj4KICogIDx0cj4KICogICA8dGQ+Si4gV2FsdGVyIFdlYXRoZXJtYW48L3RkPgogKiAgIDx0ZD5KLjwvdGQ+CiAqICAgPHRkPldhbHRlcjwvdGQ+CiAqICAgPHRkPjwvdGQ+CiAqICAgPHRkPjwvdGQ+CiAqICAgPHRkPldlYXRoZXJtYW48L3RkPgogKiAgIDx0ZD48L3RkPgogKiAgPC90cj4KICogIDx0cj4KICogICA8dGQ+ZGUgbGEgQ3J1eiwgQW5hIE0uPC90ZD4KICogICA8dGQ+PC90ZD4KICogICA8dGQ+QW5hPC90ZD4KICogICA8dGQ+PC90ZD4KICogICA8dGQ+TS48L3RkPgogKiAgIDx0ZD5kZSBsYSBDcnV6PC90ZD4KICogICA8dGQ+PC90ZD4KICogIDwvdHI+CiAqICA8dHI+CiAqICAgPHRkPkphbWVzIEMuICgnSmltbXknKSBPJ0RlbGwsIEpyLjwvdGQ+CiAqICAgPHRkPjwvdGQ+CiAqICAgPHRkPkphbWVzPC90ZD4KICogICA8dGQ+SmltbXk8L3RkPgogKiAgIDx0ZD5DLjwvdGQ+CiAqICAgPHRkPk8nRGVsbDwvdGQ+CiAqICAgPHRkPkpyLjwvdGQ+CiAqICA8L3RyPgogKiA8L3RhYmxlPgogKgogKiA8aDM+U2FtcGxlIHVzYWdlPC9oMz4KICogCiAqIDxwPkh1bWFuTmFtZVBhcnNlciBpbnN0YW5jZXMgYXJlIGltbXV0YWJsZSBhbmQgY2FuIGJlIHJldXNlZCBmb3IgcGFyc2luZyBtdWx0aXBsZSBuYW1lczo8L3A+CiAqIAogKiA8cHJlPgogKiBIdW1hbk5hbWVQYXJzZXIgcGFyc2VyID0gbmV3IEh1bWFuTmFtZVBhcnNlcigpOwogKiBOYW1lIHBhcnNlZE5hbWUgPSBwYXJzZXIucGFyc2UoIlPpcmdpbyBWaWVpcmEgZGUgTWVsbG8iKQogKiBTdHJpbmcgZmlyc3ROYW1lID0gcGFyc2VkTmFtZS5nZXRGaXJzdE5hbWUoKTsKICogU3RyaW5nIG5pY2tuYW1lID0gcGFyc2VkTmFtZS5nZXROaWNrTmFtZSgpOwogKiAvLyAuLi4KICogCiAqIE5hbWUgbmV4dE5hbWUgPSBwYXJzZXIucGFyc2UoIkphbWVzIEMuICgnSmltbXknKSBPJ0RlbGwsIEpyLiIpCiAqIFN0cmluZyBmaXJzdE5hbWUgPSBuZXh0TmFtZS5nZXRGaXJzdE5hbWUoKTsKICogU3RyaW5nIG5pY2tuYW1lID0gbmV4dE5hbWUuZ2V0Tmlja05hbWUoKTsKICogPC9wcmU+CiAqCiAqIDxoMz5GdXJ0aGVyIG5vdGVzPC9oMz4KICogCiAqIDxwPlRoZSBvcmlnaW5hbCBjb2RlIHdhcyB3cml0dGVuIGluIDxhIGhyZWY9Imh0dHA6Ly9qYXNvbnByaWVtLmNvbS9odW1hbi1uYW1lLXBhcnNlIj5QSFA8L2E+CiAqIGFuZCBwb3J0ZWQgdG8gPGEgaHJlZj0iaHR0cDovL3R1cGlsYWJzLmdpdGh1Yi5pby9IdW1hbk5hbWVQYXJzZXIuamF2YS8iPkphdmE8L2E+LiBUaGlzIAogKiBpbXBsZW1lbnRhdGlvbiBpcyBiYXNlZCBvbiB0aGUgSmF2YSBpbXBsZW1lbnRhdGlvbiwgd2l0aCBhZGRpdGlvbnMKICogc3VnZ2VzdGVkIGluIDxhIGhyZWY9Imh0dHBzOi8vaXNzdWVzLmFwYWNoZS5vcmcvamlyYS9icm93c2UvU0FOREJPWC00ODciPlNBTkRCT1gtNDg3PC9hPgogKiBhbmQgPGEgaHJlZj0iaHR0cHM6Ly9pc3N1ZXMuYXBhY2hlLm9yZy9qaXJhL2Jyb3dzZS9TQU5EQk9YLTQ5OCI+U0FOREJPWC00OTg8L2E+LjwvcD4KICoKICogPHA+VGhpcyBjbGFzcyBpcyBpbW11dGFibGUuPC9wPgogKi8KcHVibGljIGZpbmFsIGNsYXNzIEh1bWFuTmFtZVBhcnNlciB7CgogICAgcHJpdmF0ZSBmaW5hbCBMaXN0PFN0cmluZz4gc3VmZml4ZXM7CiAgICBwcml2YXRlIGZpbmFsIExpc3Q8U3RyaW5nPiBwcmVmaXhlczsKCiAgICAvKioKICAgICAqIENyZWF0ZXMgYSBuZXcgcGFyc2VyLgogICAgICovCiAgICBwdWJsaWMgSHVtYW5OYW1lUGFyc2VyKCkgewogICAgICAgIC8vIFRPRE8gbWFrZSB0aGlzIGNvbmZpZ3VyYWJsZQogICAgICAgIHRoaXMuc3VmZml4ZXMgPSBBcnJheXMuYXNMaXN0KAogICAgICAgICAgICAgICAgImVzcSIsICJlc3F1aXJlIiwgImpyIiwKICAgICAgICAgICAgICAgICJzciIsICIyIiwgImlpIiwgImlpaSIsICJpdiIpOwogICAgICAgIHRoaXMucHJlZml4ZXMgPSBBcnJheXMuYXNMaXN0KAogICAgICAgICAgICAgICAgICAgICJiYXIiLCAiYmVuIiwgImJpbiIsICJkYSIsICJkYWwiLAogICAgICAgICAgICAgICAgICAgICJkZSBsYSIsICJkZSIsICJkZWwiLCAiZGVyIiwgImRpIiwgImlibiIsICJsYSIsICJsZSIsCiAgICAgICAgICAgICAgICAgICAgInNhbiIsICJzdCIsICJzdGUiLCAidmFuIiwgInZhbiBkZXIiLCAidmFuIGRlbiIsICJ2ZWwiLAogICAgICAgICAgICAgICAgICAgICJ2b24iICk7CiAgICB9CgogICAgLyoqCiAgICAgKiBQYXJzZXMgYSBuYW1lIGZyb20gdGhlIGdpdmVuIHN0cmluZy4KICAgICAqCiAgICAgKiBAcGFyYW0gbmFtZSB0aGUgbmFtZSB0byBwYXJzZS4gTXVzdCBub3QgYmUgbnVsbC4KICAgICAqIEB0aHJvd3MgTmFtZVBhcnNlRXhjZXB0aW9uIGlmIHRoZSBwYXJzZXIgZmFpbHMgdG8gcmV0cmlldmUgdGhlIG5hbWUgcGFydHMuCiAgICAgKiBAdGhyb3dzIE51bGxQb2ludGVyRXhjZXB0aW9uIGlmIG5hbWUgaXMgbnVsbC4KICAgICAqLwogICAgcHVibGljIE5hbWUgcGFyc2UoU3RyaW5nIG5hbWUpIHsKICAgICAgICBPYmplY3RzLnJlcXVpcmVOb25OdWxsKG5hbWUsICJQYXJhbWV0ZXIgJ25hbWUnIG11c3Qgbm90IGJlIG51bGwuIik7CgogICAgICAgIE5hbWVTdHJpbmcgbmFtZVN0cmluZyA9IG5ldyBOYW1lU3RyaW5nKG5hbWUpOwogICAgICAgIC8vIFRPRE8gY29tcGlsZSByZWdleGVzIG9ubHkgb25jZSB3aGVuIHRoZSBwYXJzZXIgaXMgY3JlYXRlZAogICAgICAgIFN0cmluZyBzdWZmaXhlcyA9IFN0cmluZ1V0aWxzLmpvaW4odGhpcy5zdWZmaXhlcywgIlxcLip8IikgKyAiXFwuKiI7CiAgICAgICAgU3RyaW5nIHByZWZpeGVzID0gU3RyaW5nVXRpbHMuam9pbih0aGlzLnByZWZpeGVzLCAiIHwiKSArICIgIjsKCiAgICAgICAgLy8gVGhlIHJlZ2V4IHVzZSBpcyBhIGJpdCB0cmlja3kuICAqRXZlcnl0aGluZyogbWF0Y2hlZCBieSB0aGUgcmVnZXggd2lsbCBiZSByZXBsYWNlZCwKICAgICAgICAvLyBidXQgeW91IGNhbiBzZWxlY3QgYSBwYXJ0aWN1bGFyIHBhcmVudGhlc2l6ZWQgc3VibWF0Y2ggdG8gYmUgcmV0dXJuZWQuCiAgICAgICAgLy8gQWxzbywgbm90ZSB0aGF0IGVhY2ggcmVnZXggcmVxdXJlcyB0aGF0IHRoZSBwcmVjZWRpbmcgb25lcyBoYXZlIGJlZW4gcnVuLCBhbmQgbWF0Y2hlcyBjaG9wcGVkIG91dC4KICAgICAgICAvLyBuYW1lcyB0aGF0IHN0YXJ0cyBvciBlbmQgdy8gYW4gYXBvc3Ryb3BoZSBicmVhayB0aGlzCiAgICAgICAgU3RyaW5nIG5pY2tuYW1lc1JlZ2V4ID0gIig/aSkgKCd8XFxcInxcXChcXFwiKicqKSguKz8pKCd8XFxcInxcXFwiKicqXFwpKSAiOwogICAgICAgIFN0cmluZyBzdWZmaXhSZWdleCA9ICIoP2kpLCogKigoIiArIHN1ZmZpeGVzICsgIikkKSI7CiAgICAgICAgU3RyaW5nIGxhc3RSZWdleCA9ICIoP2kpKD8hXilcXGIoW14gXSsgeSB8IiArIHByZWZpeGVzICsgIikqW14gXSskIjsKICAgICAgICAvLyBub3RlIHRoZSBsb29rYWhlYWQsIHdoaWNoIGlzbid0IHJldHVybmVkIG9yIHJlcGxhY2VkCiAgICAgICAgU3RyaW5nIGxlYWRpbmdJbml0UmVnZXggPSAiKD9pKSheKC5cXC4qKSg/PSBcXHB7TH17Mn0pKSI7CiAgICAgICAgU3RyaW5nIGZpcnN0UmVnZXggPSAiKD9pKV4oW14gXSspIjsKCiAgICAgICAgLy8gZ2V0IG5pY2tuYW1lLCBpZiB0aGVyZSBpcyBvbmUKICAgICAgICBTdHJpbmcgbmlja25hbWUgPSBuYW1lU3RyaW5nLmNob3BXaXRoUmVnZXgobmlja25hbWVzUmVnZXgsIDIpOwoKICAgICAgICAvLyBnZXQgc3VmZml4LCBpZiB0aGVyZSBpcyBvbmUKICAgICAgICBTdHJpbmcgc3VmZml4ID0gbmFtZVN0cmluZy5jaG9wV2l0aFJlZ2V4KHN1ZmZpeFJlZ2V4LCAxKTsKCiAgICAgICAgLy8gZmxpcCB0aGUgYmVmb3JlLWNvbW1hIGFuZCBhZnRlci1jb21tYSBwYXJ0cyBvZiB0aGUgbmFtZQogICAgICAgIG5hbWVTdHJpbmcuZmxpcCgiLCIpOwoKICAgICAgICAvLyBnZXQgdGhlIGxhc3QgbmFtZQogICAgICAgIFN0cmluZyBsYXN0ID0gbmFtZVN0cmluZy5jaG9wV2l0aFJlZ2V4KGxhc3RSZWdleCwgMCk7CgogICAgICAgIC8vIGdldCB0aGUgZmlyc3QgaW5pdGlhbCwgaWYgdGhlcmUgaXMgb25lCiAgICAgICAgU3RyaW5nIGxlYWRpbmdJbml0ID0gbmFtZVN0cmluZy5jaG9wV2l0aFJlZ2V4KGxlYWRpbmdJbml0UmVnZXgsIDEpOwoKICAgICAgICAvLyBnZXQgdGhlIGZpcnN0IG5hbWUKICAgICAgICBTdHJpbmcgZmlyc3QgPSBuYW1lU3RyaW5nLmNob3BXaXRoUmVnZXgoZmlyc3RSZWdleCwgMCk7CiAgICAgICAgaWYgKFN0cmluZ1V0aWxzLmlzQmxhbmsoZmlyc3QpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOYW1lUGFyc2VFeGNlcHRpb24oIkNvdWxkbid0IGZpbmQgYSBmaXJzdCBuYW1lIGluICd7IiArIG5hbWVTdHJpbmcuZ2V0V3JhcHBlZFN0cmluZygpICsgIn0nIik7CiAgICAgICAgfQoKICAgICAgICAvLyBpZiBhbnl0aGluZydzIGxlZnQsIHRoYXQncyB0aGUgbWlkZGxlIG5hbWUKICAgICAgICBTdHJpbmcgbWlkZGxlID0gbmFtZVN0cmluZy5nZXRXcmFwcGVkU3RyaW5nKCk7CiAgICAgICAgCiAgICAgICAgcmV0dXJuIG5ldyBOYW1lKGxlYWRpbmdJbml0LCBmaXJzdCwgbmlja25hbWUsIG1pZGRsZSwgbGFzdCwgc3VmZml4KTsKICAgIH0KCn0K