LyoKICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZSBvciBtb3JlCiAqIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCiAqIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlIHRvIFlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wCiAqICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqCiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCiAqLwpwYWNrYWdlIG9yZy5hcGFjaGUuY29tbW9ucy5zYW5zZWxhbi5mb3JtYXRzLnRpZmYucGhvdG9tZXRyaWNpbnRlcnByZXRlcnM7CgppbXBvcnQgamF2YS5pby5JT0V4Y2VwdGlvbjsKCmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMuc2Fuc2VsYW4uSW1hZ2VSZWFkRXhjZXB0aW9uOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLnNhbnNlbGFuLmNvbW1vbi5JbWFnZUJ1aWxkZXI7CgpwdWJsaWMgY2xhc3MgUGhvdG9tZXRyaWNJbnRlcnByZXRlckxvZ0x1diBleHRlbmRzIFBob3RvbWV0cmljSW50ZXJwcmV0ZXIKewogICAgLy8gICAgcHJpdmF0ZSBmaW5hbCBib29sZWFuIHlPbmx5OwoKICAgIHB1YmxpYyBQaG90b21ldHJpY0ludGVycHJldGVyTG9nTHV2KGludCBmU2FtcGxlc1BlclBpeGVsLAogICAgICAgICAgICBpbnQgZkJpdHNQZXJTYW1wbGVbXSwgaW50IFByZWRpY3RvciwgaW50IHdpZHRoLCBpbnQgaGVpZ2h0LAogICAgICAgICAgICBib29sZWFuIHlvbmx5KQogICAgewogICAgICAgIHN1cGVyKGZTYW1wbGVzUGVyUGl4ZWwsIGZCaXRzUGVyU2FtcGxlLCBQcmVkaWN0b3IsIHdpZHRoLCBoZWlnaHQpOwoKICAgICAgICAvLyAgICAgICAgdGhpcy55T25seSA9IHlvbmx5OwogICAgfQoKICAgIEBPdmVycmlkZQogICAgcHVibGljIHZvaWQgZHVtcHN0YXRzKCkgdGhyb3dzIEltYWdlUmVhZEV4Y2VwdGlvbiwgSU9FeGNlcHRpb24KICAgIHsKICAgIH0KCiAgICBwcml2YXRlIGZsb2F0IGN1YmUoZmxvYXQgZikKICAgIHsKICAgICAgICByZXR1cm4gZiAqIGYgKiBmOwogICAgfQoKICAgIC8vICAgICAgICBwcml2YXRlIGZsb2F0IGZ1bmN0aW9uX2YoZmxvYXQgdmFsdWUsICkKCiAgICBAT3ZlcnJpZGUKICAgIHB1YmxpYyB2b2lkIGludGVycHJldFBpeGVsKEltYWdlQnVpbGRlciBpbWFnZUJ1aWxkZXIsIGludCBzYW1wbGVzW10sIGludCB4LCBpbnQgeSkKICAgICAgICAgICAgdGhyb3dzIEltYWdlUmVhZEV4Y2VwdGlvbiwgSU9FeGNlcHRpb24KICAgIHsKICAgICAgICBmbG9hdCBYLCBZLCBaOwoKICAgICAgICBpbnQgY2llTCA9IHNhbXBsZXNbMF07CiAgICAgICAgaW50IGNpZUEgPSAoYnl0ZSkgc2FtcGxlc1sxXTsKICAgICAgICBpbnQgY2llQiA9IChieXRlKSBzYW1wbGVzWzJdOwoKICAgICAgICB7CgogICAgICAgICAgICBmbG9hdCB2YXJfWSA9ICgoY2llTCAqIDEwMC4wZiAvIDI1NS4wZikgKyAxNi4wZikgLyAxMTYuMGY7CiAgICAgICAgICAgIGZsb2F0IHZhcl9YID0gY2llQSAvIDUwMC4wZiArIHZhcl9ZOwogICAgICAgICAgICBmbG9hdCB2YXJfWiA9IHZhcl9ZIC0gY2llQiAvIDIwMC4wZjsKCiAgICAgICAgICAgIGZsb2F0IHZhcl94X2N1YmUgPSBjdWJlKHZhcl9YKTsKICAgICAgICAgICAgZmxvYXQgdmFyX3lfY3ViZSA9IGN1YmUodmFyX1kpOwogICAgICAgICAgICBmbG9hdCB2YXJfel9jdWJlID0gY3ViZSh2YXJfWik7CgogICAgICAgICAgICBpZiAodmFyX3lfY3ViZSA+IDAuMDA4ODU2ZikKICAgICAgICAgICAgICAgIHZhcl9ZID0gdmFyX3lfY3ViZTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgdmFyX1kgPSAodmFyX1kgLSAxNiAvIDExNi4wZikgLyA3Ljc4N2Y7CgogICAgICAgICAgICBpZiAodmFyX3hfY3ViZSA+IDAuMDA4ODU2ZikKICAgICAgICAgICAgICAgIHZhcl9YID0gdmFyX3hfY3ViZTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgdmFyX1ggPSAodmFyX1ggLSAxNiAvIDExNi4wZikgLyA3Ljc4N2Y7CgogICAgICAgICAgICBpZiAodmFyX3pfY3ViZSA+IDAuMDA4ODU2ZikKICAgICAgICAgICAgICAgIHZhcl9aID0gdmFyX3pfY3ViZTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgdmFyX1ogPSAodmFyX1ogLSAxNiAvIDExNi4wZikgLyA3Ljc4N2Y7CgogICAgICAgICAgICBmbG9hdCByZWZfWCA9IDk1LjA0N2Y7CiAgICAgICAgICAgIGZsb2F0IHJlZl9ZID0gMTAwLjAwMGY7CiAgICAgICAgICAgIGZsb2F0IHJlZl9aID0gMTA4Ljg4M2Y7CgogICAgICAgICAgICBYID0gcmVmX1ggKiB2YXJfWDsgLy9yZWZfWCA9ICA5NS4wNDcgIE9ic2VydmVyPSAysCwgSWxsdW1pbmFudD0gRDY1CiAgICAgICAgICAgIFkgPSByZWZfWSAqIHZhcl9ZOyAvL3JlZl9ZID0gMTAwLjAwMAogICAgICAgICAgICBaID0gcmVmX1ogKiB2YXJfWjsgLy9yZWZfWiA9IDEwOC44ODMKCiAgICAgICAgfQoKICAgICAgICAvLyAgICAgICAgICAgIHJlZl9YID0gIDk1LjA0NyAgICAgICAgLy9PYnNlcnZlciA9IDKwLCBJbGx1bWluYW50ID0gRDY1CiAgICAgICAgLy8gICAgICAgICAgICByZWZfWSA9IDEwMC4wMDAKICAgICAgICAvLyAgICAgICAgICAgIHJlZl9aID0gMTA4Ljg4MwoKICAgICAgICBpbnQgUiwgRywgQjsKICAgICAgICB7CiAgICAgICAgICAgIGZsb2F0IHZhcl9YID0gWCAvIDEwMGY7IC8vWCA9IEZyb20gMCB0byByZWZfWAogICAgICAgICAgICBmbG9hdCB2YXJfWSA9IFkgLyAxMDBmOyAvL1kgPSBGcm9tIDAgdG8gcmVmX1kKICAgICAgICAgICAgZmxvYXQgdmFyX1ogPSBaIC8gMTAwZjsgLy9aID0gRnJvbSAwIHRvIHJlZl9ZCgogICAgICAgICAgICBmbG9hdCB2YXJfUiA9IHZhcl9YICogMy4yNDA2ZiArIHZhcl9ZICogLTEuNTM3MmYgKyB2YXJfWiAqIC0wLjQ5ODZmOwogICAgICAgICAgICBmbG9hdCB2YXJfRyA9IHZhcl9YICogLTAuOTY4OWYgKyB2YXJfWSAqIDEuODc1OGYgKyB2YXJfWiAqIDAuMDQxNWY7CiAgICAgICAgICAgIGZsb2F0IHZhcl9CID0gdmFyX1ggKiAwLjA1NTdmICsgdmFyX1kgKiAtMC4yMDQwZiArIHZhcl9aICogMS4wNTcwZjsKCiAgICAgICAgICAgIGlmICh2YXJfUiA+IDAuMDAzMTMwOCkKICAgICAgICAgICAgICAgIHZhcl9SID0gMS4wNTVmICogKGZsb2F0KSBNYXRoLnBvdyh2YXJfUiwgKDEgLyAyLjQpKSAtIDAuMDU1ZjsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgdmFyX1IgPSAxMi45MmYgKiB2YXJfUjsKICAgICAgICAgICAgaWYgKHZhcl9HID4gMC4wMDMxMzA4KQogICAgICAgICAgICAgICAgdmFyX0cgPSAxLjA1NWYgKiAoZmxvYXQpIE1hdGgucG93KHZhcl9HLCAoMSAvIDIuNCkpIC0gMC4wNTVmOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICB2YXJfRyA9IDEyLjkyZiAqIHZhcl9HOwoKICAgICAgICAgICAgaWYgKHZhcl9CID4gMC4wMDMxMzA4KQogICAgICAgICAgICAgICAgdmFyX0IgPSAxLjA1NWYgKiAoZmxvYXQpIE1hdGgucG93KHZhcl9CLCAoMSAvIDIuNCkpIC0gMC4wNTVmOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICB2YXJfQiA9IDEyLjkyZiAqIHZhcl9COwoKICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgdmFyX1IgPSAoKCh2YXJfUi0pKSkKICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgdXBkYXRlTWF4TWluKG5ldyBmbG9hdFtdewogICAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgIHZhcl9SLCB2YXJfRywgdmFyX0IsCiAgICAgICAgICAgIC8vICAgICAgICAgICAgICAgIH0sIG1heFZhclJHQiwgbWluVmFyUkdCKTsKCiAgICAgICAgICAgIC8vICAgICAgICAgICAgICAgIHZhcl9SID0gKCh2YXJfUiArIDAuMTY1NjEwMzlmKSAvICgzLjAxNTI1ODNmICsgMC4xNjU2MTAzOWYpKTsKICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgdmFyX0cgPSAoKHZhcl9HICsgMC4wNjU2MTY0MmYpIC8gKDMuMDIzOTg1NGYgKyAwLjA2NTYxNjQyZikpOwogICAgICAgICAgICAvLyAgICAgICAgICAgICAgICB2YXJfQiA9ICgodmFyX0IgKyAwLjE5MzkzOTkyZikgLyAoMy4xMDQzNDQ4ZiArIDAuMTkzOTM5OTJmKSk7CgogICAgICAgICAgICBSID0gKGludCkgKHZhcl9SICogMjU1Zik7CiAgICAgICAgICAgIEcgPSAoaW50KSAodmFyX0cgKiAyNTVmKTsKICAgICAgICAgICAgQiA9IChpbnQpICh2YXJfQiAqIDI1NWYpOwogICAgICAgIH0KCiAgICAgICAgLy8gICAgICAgICAgICBmbG9hdCBSID0gMS45MTBmICogWCAtIDAuNTMyZiAqIFkgLSAwLjI4OGYgKiBaOwogICAgICAgIC8vICAgICAgICAgICAgZmxvYXQgRyA9IC0wLjk4NWYgKiBYICsgMS45OTlmICogWSAtIDAuMDI4ZiAqIFo7CiAgICAgICAgLy8gICAgICAgICAgICBmbG9hdCBCID0gMC4wNThmICogWCAtIDAuMTE4ZiAqIFkgKyAwLjg5OGYgKiBaOwoKICAgICAgICAvLyAgICAgICAgICAgIHVwZGF0ZU1heE1pbihuZXcgZmxvYXRbXXsKICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgUiwgRywgQiwKICAgICAgICAvLyAgICAgICAgICAgIH0sIG1heFJHQiwgbWluUkdCKTsKCiAgICAgICAgaW50IHJlZCA9IFI7CiAgICAgICAgaW50IGdyZWVuID0gRzsKICAgICAgICBpbnQgYmx1ZSA9IEI7CgogICAgICAgIHJlZCA9IE1hdGgubWluKDI1NSwgTWF0aC5tYXgoMCwgcmVkKSk7CiAgICAgICAgZ3JlZW4gPSBNYXRoLm1pbigyNTUsIE1hdGgubWF4KDAsIGdyZWVuKSk7CiAgICAgICAgYmx1ZSA9IE1hdGgubWluKDI1NSwgTWF0aC5tYXgoMCwgYmx1ZSkpOwogICAgICAgIGludCBhbHBoYSA9IDB4ZmY7CiAgICAgICAgaW50IHJnYiA9IChhbHBoYSA8PCAyNCkgfCAocmVkIDw8IDE2KSB8IChncmVlbiA8PCA4KSB8IChibHVlIDw8IDApOwogICAgICAgIGltYWdlQnVpbGRlci5zZXRSR0IoeCwgeSwgcmdiKTsKCiAgICB9Cn0=