cGFja2FnZSBvcmcuZWNsaXBzZS54dGVuZC5saWIuYW5ub3RhdGlvbnMKCmltcG9ydCBjb20uZ29vZ2xlLmNvbW1vbi5hbm5vdGF0aW9ucy5CZXRhCmltcG9ydCBjb20uZ29vZ2xlLmNvbW1vbi5hbm5vdGF0aW9ucy5Hd3RDb21wYXRpYmxlCmltcG9ydCBqYXZhLmxhbmcuYW5ub3RhdGlvbi5FbGVtZW50VHlwZQppbXBvcnQgamF2YS5sYW5nLmFubm90YXRpb24uVGFyZ2V0CmltcG9ydCBvcmcuZWNsaXBzZS54dGVuZC5saWIubWFjcm8uQWJzdHJhY3RDbGFzc1Byb2Nlc3NvcgppbXBvcnQgb3JnLmVjbGlwc2UueHRlbmQubGliLm1hY3JvLkFjdGl2ZQppbXBvcnQgb3JnLmVjbGlwc2UueHRlbmQubGliLm1hY3JvLlRyYW5zZm9ybWF0aW9uQ29udGV4dAppbXBvcnQgb3JnLmVjbGlwc2UueHRlbmQubGliLm1hY3JvLmRlY2xhcmF0aW9uLkNsYXNzRGVjbGFyYXRpb24KaW1wb3J0IG9yZy5lY2xpcHNlLnh0ZW5kLmxpYi5tYWNyby5kZWNsYXJhdGlvbi5GaWVsZERlY2xhcmF0aW9uCmltcG9ydCBvcmcuZWNsaXBzZS54dGVuZC5saWIubWFjcm8uZGVjbGFyYXRpb24uTXV0YWJsZUNsYXNzRGVjbGFyYXRpb24KaW1wb3J0IG9yZy5lY2xpcHNlLnh0ZW5kLmxpYi5tYWNyby5kZWNsYXJhdGlvbi5UeXBlUmVmZXJlbmNlCmltcG9ydCBvcmcuZWNsaXBzZS54dGVuZDIubGliLlN0cmluZ0NvbmNhdGVuYXRpb25DbGllbnQKaW1wb3J0IGphdmEudXRpbC5BcnJheXMKCi8qKgogKiBDcmVhdGVzIGRlZmF1bHQgaW1wbGVtZW50YXRpb25zIGZvciB7QGxpbmsgT2JqZWN0I2VxdWFscyhPYmplY3QpIGVxdWFsc30gYW5kIHtAbGluayBPYmplY3QjaGFzaENvZGUgaGFzaENvZGV9LgogKiAKICogQWxsIG5vbi1zdGF0aWMsIG5vbi10cmFuc2llbnQgZmllbGRzIGFyZSB1c2VkLiBTdWJjbGFzc2VzIGFyZSBuZXZlciBlcXVhbCB0byB0aGVpciBzdXBlcmNsYXNzZXMuIAogKiBJZiB0aGVyZSBpcyBhIHN1cGVyY2xhc3MgdGhhdCBvdmVycmlkZXMgZXF1YWxzLCB0aGVuIDxjb2RlPnN1cGVyLmVxdWFscygpPC9jb2RlPiBhbmQgPGNvZGU+c3VwZXIuaGFzaENvZGU8L2NvZGU+IGFyZSBhbHNvIGNhbGxlZC4KICogQXJyYXktdmFsdWVkIGZpZWxkcyBhcmUgY29tcGFyZWQgdXNpbmcgI3tAbGluayBBcnJheXMjZGVlcEVxdWFsc30uCiAqIEBzaW5jZSAyLjcKICovCkBCZXRhCkBHd3RDb21wYXRpYmxlCkBUYXJnZXQoRWxlbWVudFR5cGUuVFlQRSkKQEFjdGl2ZShFcXVhbHNIYXNoQ29kZVByb2Nlc3NvcikKYW5ub3RhdGlvbiBFcXVhbHNIYXNoQ29kZSB7Cn0KCi8qKgogKiBAc2luY2UgMi43CiAqIEBub3JlZmVyZW5jZQogKiBAbm9leHRlbmQKICovCkBCZXRhCmNsYXNzIEVxdWFsc0hhc2hDb2RlUHJvY2Vzc29yIGV4dGVuZHMgQWJzdHJhY3RDbGFzc1Byb2Nlc3NvciB7CgoJb3ZlcnJpZGUgZG9UcmFuc2Zvcm0oTXV0YWJsZUNsYXNzRGVjbGFyYXRpb24gaXQsIGV4dGVuc2lvbiBUcmFuc2Zvcm1hdGlvbkNvbnRleHQgY29udGV4dCkgewoJCWlmIChmaW5kQW5ub3RhdGlvbihEYXRhLmZpbmRUeXBlR2xvYmFsbHkpICE9PSBudWxsKSB7CgkJCXJldHVybgoJCX0KCQlleHRlbnNpb24gdmFsIHV0aWwgPSBuZXcgVXRpbChjb250ZXh0KQoJCWlmIChoYXNFcXVhbHMpIHsKCQkJdmFsIGFubm90YXRpb24gPSBmaW5kQW5ub3RhdGlvbihFcXVhbHNIYXNoQ29kZS5maW5kVHlwZUdsb2JhbGx5KQoJCQlhbm5vdGF0aW9uLmFkZFdhcm5pbmcoImVxdWFscyBpcyBhbHJlYWR5IGRlZmluZWQsIHRoaXMgYW5ub3RhdGlvbiBoYXMgbm8gZWZmZWN0IikKCQl9IGVsc2UgaWYgKGhhc0hhc2hDb2RlKSB7CgkJCWFkZFdhcm5pbmcoImhhc2hDb2RlIGlzIGFscmVhZHkgZGVmaW5lZCwgdGhpcyBhbm5vdGF0aW9uIGhhcyBubyBlZmZlY3QiKQoJCX0gZWxzZSB7CgkJCXZhbCBmaWVsZHMgPSBkZWNsYXJlZEZpZWxkcy5maWx0ZXJbIXN0YXRpYyAmJiAhdHJhbnNpZW50ICYmIHRoZVByaW1hcnlHZW5lcmF0ZWRKYXZhRWxlbWVudF0KCQkJYWRkRXF1YWxzKGZpZWxkcywgaGFzU3VwZXJFcXVhbHMpCgkJCWFkZEhhc2hDb2RlKGZpZWxkcywgaGFzU3VwZXJIYXNoQ29kZSkKCQl9Cgl9CgoJLyoqCgkgKiBAc2luY2UgMi43CgkgKiBAbm9leHRlbmQKCSAqIEBub3JlZmVyZW5jZQogCSAqLwoJQEJldGEKCXN0YXRpYyBjbGFzcyBVdGlsIHsKCgkJc3RhdGljIGZpbmFsIGludCBQUklNRV9WQUxVRSA9IDMxCgkJZXh0ZW5zaW9uIFRyYW5zZm9ybWF0aW9uQ29udGV4dCBjb250ZXh0CgoJCW5ldyhUcmFuc2Zvcm1hdGlvbkNvbnRleHQgY29udGV4dCkgewoJCQl0aGlzLmNvbnRleHQgPSBjb250ZXh0CgkJfQoKCQlkZWYgaGFzSGFzaENvZGUoQ2xhc3NEZWNsYXJhdGlvbiBpdCkgewoJCQlmaW5kRGVjbGFyZWRNZXRob2QoImhhc2hDb2RlIikgIT09IG51bGwKCQl9CgoJCWRlZiBoYXNFcXVhbHMoQ2xhc3NEZWNsYXJhdGlvbiBpdCkgewoJCQlkZWNsYXJlZE1ldGhvZHMuZXhpc3RzIFsKCQkJCXNpbXBsZU5hbWUgPT0gImVxdWFscyIgJiYgcGFyYW1ldGVycy5zaXplID09IDEgJiYgcGFyYW1ldGVycy5oZWFkLnR5cGUgPT0gb2JqZWN0CgkJCV0KCQl9CgoJCWRlZiBib29sZWFuIGhhc1N1cGVyRXF1YWxzKENsYXNzRGVjbGFyYXRpb24gY2xzKSB7CgkJCXZhbCBzdXBlckNsYXNzID0gKGNscy5leHRlbmRlZENsYXNzLnR5cGUgYXMgQ2xhc3NEZWNsYXJhdGlvbikKCQkJaWYgKHN1cGVyQ2xhc3MubmV3VHlwZVJlZmVyZW5jZS5lcXVhbHMob2JqZWN0KSkgewoJCQkJZmFsc2UKCQkJfSBlbHNlIGlmIChzdXBlckNsYXNzLmhhc0VxdWFscykgewoJCQkJdHJ1ZQoJCQl9IGVsc2UgewoJCQkJc3VwZXJDbGFzcy5oYXNTdXBlckVxdWFscwoJCQl9CgkJfQoJCWRlZiBib29sZWFuIGhhc1N1cGVySGFzaENvZGUoQ2xhc3NEZWNsYXJhdGlvbiBjbHMpIHsKCQkJdmFsIHN1cGVyQ2xhc3MgPSAoY2xzLmV4dGVuZGVkQ2xhc3MudHlwZSBhcyBDbGFzc0RlY2xhcmF0aW9uKQoJCQlpZiAoc3VwZXJDbGFzcy5uZXdUeXBlUmVmZXJlbmNlLmVxdWFscyhvYmplY3QpKSB7CgkJCQlmYWxzZQoJCQl9IGVsc2UgaWYgKHN1cGVyQ2xhc3MuaGFzSGFzaENvZGUpIHsKCQkJCXRydWUKCQkJfSBlbHNlIHsKCQkJCXN1cGVyQ2xhc3MuaGFzU3VwZXJIYXNoQ29kZQoJCQl9CgkJfQoKCQlkZWYgdm9pZCBhZGRFcXVhbHMoTXV0YWJsZUNsYXNzRGVjbGFyYXRpb24gY2xzLCBJdGVyYWJsZTw/IGV4dGVuZHMgRmllbGREZWNsYXJhdGlvbj4gaW5jbHVkZWRGaWVsZHMsCgkJCWJvb2xlYW4gaW5jbHVkZVN1cGVyKSB7CgkJCWNscy5hZGRNZXRob2QoImVxdWFscyIpIFsKCQkJCXByaW1hcnlTb3VyY2VFbGVtZW50ID0gY2xzLnByaW1hcnlTb3VyY2VFbGVtZW50CgkJCQlyZXR1cm5UeXBlID0gcHJpbWl0aXZlQm9vbGVhbgoJCQkJYWRkQW5ub3RhdGlvbihuZXdBbm5vdGF0aW9uUmVmZXJlbmNlKE92ZXJyaWRlKSkKCQkJCWFkZEFubm90YXRpb24obmV3QW5ub3RhdGlvblJlZmVyZW5jZShQdXJlKSkKCQkJCWFkZFBhcmFtZXRlcigib2JqIiwgb2JqZWN0KQoJCQkJYm9keSA9ICcnJwoJCQkJCWlmICh0aGlzID09IG9iaikKCQkJCQkgIHJldHVybiB0cnVlOwoJCQkJCWlmIChvYmogPT0gbnVsbCkKCQkJCQkgIHJldHVybiBmYWxzZTsKCQkJCQlpZiAoZ2V0Q2xhc3MoKSAhPSBvYmouZ2V0Q2xhc3MoKSkKCQkJCQkgIHJldHVybiBmYWxzZTsKCQkJCQmrSUYgaW5jbHVkZVN1cGVyuwoJCQkJCQlpZiAoIXN1cGVyLmVxdWFscyhvYmopKQoJCQkJCQkgIHJldHVybiBmYWxzZTsKCQkJCQmrRU5ESUa7CgkJCQkJq0lGIGluY2x1ZGVkRmllbGRzLnNpemU+MLsKCQkJCQkJq2Nscy5uZXdXaWxkQ2FyZFNlbGZUeXBlUmVmZXJlbmNluyBvdGhlciA9ICirY2xzLm5ld1dpbGRDYXJkU2VsZlR5cGVSZWZlcmVuY2W7KSBvYmo7CgkJCQkJq0VORElGuwoJCQkJCatGT1IgZmllbGQgOiBpbmNsdWRlZEZpZWxkc7sKCQkJCQkJq2ZpZWxkLmNvbnRyaWJ1dGVUb0VxdWFsc7sKCQkJCQmrRU5ERk9SuwoJCQkJCXJldHVybiB0cnVlOwoJCQkJJycnCgkJCV0KCQl9CgoJCXByaXZhdGUgZGVmIG5ld1dpbGRDYXJkU2VsZlR5cGVSZWZlcmVuY2UoQ2xhc3NEZWNsYXJhdGlvbiBjbHMpIHsKCQkJY2xzLm5ld1R5cGVSZWZlcmVuY2UoY2xzLnR5cGVQYXJhbWV0ZXJzLm1hcFtvYmplY3QubmV3V2lsZGNhcmRUeXBlUmVmZXJlbmNlXSkKCQl9CgoJCWRlZiBTdHJpbmdDb25jYXRlbmF0aW9uQ2xpZW50IGNvbnRyaWJ1dGVUb0VxdWFscyhGaWVsZERlY2xhcmF0aW9uIGl0KSB7CgkJCXN3aXRjaCAodHlwZS5vck9iamVjdC5uYW1lKSB7CgkJCQljYXNlIERvdWJsZS5UWVBFLm5hbWU6ICcnJwoJCQkJCWlmICirRG91Ymxluy5kb3VibGVUb0xvbmdCaXRzKG90aGVyLqtzaW1wbGVOYW1luykgIT0gq0RvdWJsZbsuZG91YmxlVG9Mb25nQml0cyh0aGlzLqtzaW1wbGVOYW1luykpCgkJCQkJICByZXR1cm4gZmFsc2U7IAoJCQkJJycnCgkJCQljYXNlIEZsb2F0LlRZUEUubmFtZTogJycnCgkJCQkJaWYgKKtGbG9hdLsuZmxvYXRUb0ludEJpdHMob3RoZXIuq3NpbXBsZU5hbWW7KSAhPSCrRmxvYXS7LmZsb2F0VG9JbnRCaXRzKHRoaXMuq3NpbXBsZU5hbWW7KSkKCQkJCQkgIHJldHVybiBmYWxzZTsgCgkJCQknJycKCQkJCWNhc2UgQm9vbGVhbi5UWVBFLm5hbWUsCgkJCQljYXNlIEludGVnZXIuVFlQRS5uYW1lLAoJCQkJY2FzZSBDaGFyYWN0ZXIuVFlQRS5uYW1lLAoJCQkJY2FzZSBCeXRlLlRZUEUubmFtZSwKCQkJCWNhc2UgU2hvcnQuVFlQRS5uYW1lLAoJCQkJY2FzZSBMb25nLlRZUEUubmFtZTogJycnCgkJCQkJaWYgKG90aGVyLqtzaW1wbGVOYW1luyAhPSB0aGlzLqtzaW1wbGVOYW1luykKCQkJCQkgIHJldHVybiBmYWxzZTsKCQkJCScnJwoJCQkJZGVmYXVsdDogJycnCgkJCQkJaWYgKHRoaXMuq3NpbXBsZU5hbWW7ID09IG51bGwpIHsKCQkJCQkgIGlmIChvdGhlci6rc2ltcGxlTmFtZbsgIT0gbnVsbCkKCQkJCQkgICAgcmV0dXJuIGZhbHNlOwoJCQkJCX0gZWxzZSBpZiAoIatkZWVwRXF1YWxzuykKCQkJCQkgIHJldHVybiBmYWxzZTsKCQkJCScnJwoJCQl9CgkJfQoJCQoJCWRlZiBTdHJpbmdDb25jYXRlbmF0aW9uQ2xpZW50IGRlZXBFcXVhbHMoRmllbGREZWNsYXJhdGlvbiBpdCkgewoJCQlpZiAodHlwZS5pc0FycmF5KSB7CgkJCQlpZiAodHlwZS5hcnJheUNvbXBvbmVudFR5cGUuaXNQcmltaXRpdmUpIHsKCQkJCQknJyerQXJyYXlzuy5lcXVhbHModGhpcy6rc2ltcGxlTmFtZbssIG90aGVyLqtzaW1wbGVOYW1luyknJycKCQkJCX0gZWxzZSB7CgkJCQkJJycnq0FycmF5c7suZGVlcEVxdWFscyh0aGlzLqtzaW1wbGVOYW1luywgb3RoZXIuq3NpbXBsZU5hbWW7KScnJwoJCQkJfQoJCQl9IGVsc2UgewoJCQkJJycndGhpcy6rc2ltcGxlTmFtZbsuZXF1YWxzKG90aGVyLqtzaW1wbGVOYW1luyknJycKCQkJfQoJCX0KCgkJZGVmIHZvaWQgYWRkSGFzaENvZGUoTXV0YWJsZUNsYXNzRGVjbGFyYXRpb24gY2xzLCBJdGVyYWJsZTw/IGV4dGVuZHMgRmllbGREZWNsYXJhdGlvbj4gaW5jbHVkZWRGaWVsZHMsCgkJCWJvb2xlYW4gaW5jbHVkZVN1cGVyKSB7CgkJCXZhbCBkZWZhdWx0QmFzZSA9IGlmKGluY2x1ZGVTdXBlcikgInN1cGVyLmhhc2hDb2RlKCkiIGVsc2UgIjEiCgkJCXZhbCBmaWVsZHMgPSBpbmNsdWRlZEZpZWxkcy5zaXplCgoJCQljbHMuYWRkTWV0aG9kKCJoYXNoQ29kZSIpIFsKCQkJCXByaW1hcnlTb3VyY2VFbGVtZW50ID0gY2xzLnByaW1hcnlTb3VyY2VFbGVtZW50CgkJCQlyZXR1cm5UeXBlID0gcHJpbWl0aXZlSW50CgkJCQlhZGRBbm5vdGF0aW9uKG5ld0Fubm90YXRpb25SZWZlcmVuY2UoT3ZlcnJpZGUpKQoJCQkJYWRkQW5ub3RhdGlvbihuZXdBbm5vdGF0aW9uUmVmZXJlbmNlKFB1cmUpKQoJCQkJYm9keSA9ICcnJwoJCQkJCatJRiBmaWVsZHMgPj0gMrsKCQkJCQkJZmluYWwgaW50IHByaW1lID0gq1BSSU1FX1ZBTFVFuzsKCQkJCQkJaW50IHJlc3VsdCA9IKtkZWZhdWx0QmFzZbs7CgkJCQkJCatGT1IgaSA6IDAgLi48IGZpZWxkc7sKCQkJCQkJCatJRiBpID09IGZpZWxkcyAtIDG7cmV0dXJuq0VMU0W7cmVzdWx0ID2rRU5ESUa7IHByaW1lICogcmVzdWx0ICsgq2luY2x1ZGVkRmllbGRzLmdldChpKS5jb250cmlidXRlVG9IYXNoQ29kZbs7CgkJCQkJCatFTkRGT1K7CgkJCQkJq0VMU0VJRiBmaWVsZHMgPT0gMbsKCQkJCQkJcmV0dXJuIKtQUklNRV9WQUxVRbsgKiCrZGVmYXVsdEJhc2W7ICsgq2luY2x1ZGVkRmllbGRzLmhlYWQuY29udHJpYnV0ZVRvSGFzaENvZGW7OwoJCQkJCatFTFNFuwoJCQkJCQlyZXR1cm4gq2RlZmF1bHRCYXNluzsKCQkJCQmrRU5ESUa7CgkJCQknJycKCQkJXQoJCX0KCgkJZGVmIFN0cmluZ0NvbmNhdGVuYXRpb25DbGllbnQgY29udHJpYnV0ZVRvSGFzaENvZGUoRmllbGREZWNsYXJhdGlvbiBpdCkgewoJCQlzd2l0Y2ggKHR5cGUub3JPYmplY3QubmFtZSkgewoJCQkJY2FzZSBEb3VibGUuVFlQRS5uYW1lOgoJCQkJCScnJyhpbnQpICirRG91Ymxluy5kb3VibGVUb0xvbmdCaXRzKHRoaXMuq3NpbXBsZU5hbWW7KSBeICirRG91Ymxluy5kb3VibGVUb0xvbmdCaXRzKHRoaXMuq3NpbXBsZU5hbWW7KSA+Pj4gMzIpKScnJwoJCQkJY2FzZSBGbG9hdC5UWVBFLm5hbWU6CgkJCQkJJycnq0Zsb2F0uy5mbG9hdFRvSW50Qml0cyh0aGlzLqtzaW1wbGVOYW1luyknJycKCQkJCWNhc2UgQm9vbGVhbi5UWVBFLm5hbWU6CgkJCQkJJycnKHRoaXMuq3NpbXBsZU5hbWW7ID8gMTIzMSA6IDEyMzcpJycnCgkJCQljYXNlIEludGVnZXIuVFlQRS5uYW1lLAoJCQkJY2FzZSBDaGFyYWN0ZXIuVFlQRS5uYW1lLAoJCQkJY2FzZSBCeXRlLlRZUEUubmFtZSwKCQkJCWNhc2UgU2hvcnQuVFlQRS5uYW1lOgoJCQkJCScnJ3RoaXMuq3NpbXBsZU5hbWW7JycnCgkJCQljYXNlIExvbmcuVFlQRS5uYW1lOgoJCQkJCScnJyhpbnQpICh0aGlzLqtzaW1wbGVOYW1luyBeICh0aGlzLqtzaW1wbGVOYW1luyA+Pj4gMzIpKScnJwoJCQkJZGVmYXVsdDoKCQkJCQknJycoKHRoaXMuq3NpbXBsZU5hbWW7PT0gbnVsbCkgPyAwIDogq2RlZXBIYXNoQ29kZbspJycnCgkJCX0KCQl9CgkJCgkJZGVmIFN0cmluZ0NvbmNhdGVuYXRpb25DbGllbnQgZGVlcEhhc2hDb2RlKEZpZWxkRGVjbGFyYXRpb24gaXQpIHsKCQkJdmFsIHR5cGUgPSB0eXBlLm9yT2JqZWN0CgkJCWlmICh0eXBlLmlzQXJyYXkpIHsKCQkJCWlmICh0eXBlLmFycmF5Q29tcG9uZW50VHlwZS5pc1ByaW1pdGl2ZSkgewoJCQkJCScnJ6tBcnJheXO7Lmhhc2hDb2RlKHRoaXMuq3NpbXBsZU5hbWW7KScnJwoJCQkJfSBlbHNlIHsKCQkJCQknJyerQXJyYXlzuy5kZWVwSGFzaENvZGUodGhpcy6rc2ltcGxlTmFtZbspJycnCgkJCQl9CgkJCX0gZWxzZSB7CgkJCQknJyd0aGlzLqtzaW1wbGVOYW1luy5oYXNoQ29kZSgpJycnCgkJCX0KCQl9CgkJCgkJcHJpdmF0ZSBkZWYgb3JPYmplY3QoVHlwZVJlZmVyZW5jZSByZWYpIHsKCQkJcmVmID86IG9iamVjdAoJCX0KCX0KfQo=