LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbDsKCmltcG9ydCBqYXZhLnV0aWwuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRmlsZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLklGb2xkZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5SZXNvdXJjZXNQbHVnaW47CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5qb2JzLkpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLmRlYnVnLmNvcmUuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5vc2dpLnV0aWwuTkxTOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLio7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUubW9kZWwuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS51dGlsLlNvY2tldFV0aWw7Ci8qKgogKiAKICovCnB1YmxpYyBjbGFzcyBTZXJ2ZXIgZXh0ZW5kcyBCYXNlIGltcGxlbWVudHMgSVNlcnZlciB7CgkvKioKCSAqIFNlcnZlciBpZCBhdHRyaWJ1dGUgKHZhbHVlICJzZXJ2ZXItaWQiKSBvZiBsYXVuY2ggY29uZmlndXJhdGlvbnMuCgkgKiBUaGlzIGF0dHJpYnV0ZSBpcyB1c2VkIHRvIHRhZyBhIGxhdW5jaCBjb25maWd1cmF0aW9uIHdpdGggdGhlCgkgKiBpZCBvZiB0aGUgY29ycmVzcG9uZGluZyBzZXJ2ZXIuCgkgKiAKCSAqIEBzZWUgSUxhdW5jaENvbmZpZ3VyYXRpb24KCSAqLwoJcHVibGljIHN0YXRpYyBmaW5hbCBTdHJpbmcgQVRUUl9TRVJWRVJfSUQgPSAic2VydmVyLWlkIjsKCglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIExpc3QgRU1QVFlfTElTVCA9IG5ldyBBcnJheUxpc3QoMCk7CgkKCS8qKgoJICogRmlsZSBleHRlbnNpb24gKHZhbHVlICJzZXJ2ZXIiKSBmb3Igc2VyaWFsaXplZCByZXByZXNlbnRhdGlvbiBvZgoJICogc2VydmVyIGluc3RhbmNlcy4KCSAqIDxwPgoJICogW2lzc3VlOiBXaGF0IGlzIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoaXMgZmlsZSBleHRlbnNpb24gYW5kCgkgKiB0aGUgZmlsZSBwYXNzZWQgdG8gSVNlcnZlclR5cGUuY3JlYXRlKC4uLikgb3IgcmV0dXJuZWQgYnkKCSAqIElTZXJ2ZXIuZ2V0RmlsZSgpPyBUaGF0IGlzLCBhcmUgc2VydmVyIGZpbGVzIGV4cGVjdGVkIHRvIGVuZAoJICogaW4gIi5zZXJ2ZXIiLCBvciBpcyB0aGlzIGp1c3QgYSBkZWZhdWx0PyBJZiB0aGUgZm9ybWVyCgkgKiAoYXMgSSBzdXNwZWN0KSwgdGhlbiBJU2VydmVyVHlwZS5jcmVhdGUgbmVlZHMgdG8gc2F5IHNvLAoJICogYW5kIHRoZSBpbXBsZW1lbnRhdGlvbiBzaG91bGQgZW5mb3JjZSB0aGUgcmVzdHJpY3Rpb24uXQoJICogPC9wPgoJICovCglwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBGSUxFX0VYVEVOU0lPTiA9ICJzZXJ2ZXIiOwoJCglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZyBQUk9QX0hPU1ROQU1FID0gImhvc3RuYW1lIjsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIFNFUlZFUl9JRCA9ICJzZXJ2ZXItaWQiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgUlVOVElNRV9JRCA9ICJydW50aW1lLWlkIjsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIENPTkZJR1VSQVRJT05fSUQgPSAiY29uZmlndXJhdGlvbi1pZCI7Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZyBNT0RVTEVfTElTVCA9ICJtb2R1bGVzIjsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIFBST1BfQVVUT19QVUJMSVNIX1RJTUUgPSAiYXV0by1wdWJsaXNoLXRpbWUiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgUFJPUF9BVVRPX1BVQkxJU0hfREVGQVVMVCA9ICJhdXRvLXB1Ymxpc2gtZGVmYXVsdCI7CgoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBjaGFyW10gSU5WQUxJRF9DSEFSUyA9IG5ldyBjaGFyW10geydcXCcsICcvJywgJzonLCAnKicsICc/JywgJyInLCAnPCcsICc+JywgJ3wnLCAnXDAnLCAnQCcsICcmJ307CgoJcHJvdGVjdGVkIElTZXJ2ZXJUeXBlIHNlcnZlclR5cGU7Cglwcm90ZWN0ZWQgU2VydmVyRGVsZWdhdGUgZGVsZWdhdGU7Cglwcm90ZWN0ZWQgU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUgYmVoYXZpb3VyRGVsZWdhdGU7CgoJcHJvdGVjdGVkIElSdW50aW1lIHJ1bnRpbWU7Cglwcm90ZWN0ZWQgSUZvbGRlciBjb25maWd1cmF0aW9uOwoJCgkvLyB0aGUgbGlzdCBvZiBtb2R1bGVzIHRoYXQgYXJlIHRvIGJlIHB1Ymxpc2hlZCB0byB0aGUgc2VydmVyCglwcm90ZWN0ZWQgTGlzdCBtb2R1bGVzOwoJCgkvLyB0cmFuc2llbnQgZmllbGRzCglwcm90ZWN0ZWQgdHJhbnNpZW50IFN0cmluZyBtb2RlID0gSUxhdW5jaE1hbmFnZXIuUlVOX01PREU7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGludCBzZXJ2ZXJTdGF0ZSA9IFNUQVRFX1VOS05PV047Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGludCBzZXJ2ZXJTeW5jU3RhdGU7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGJvb2xlYW4gc2VydmVyUmVzdGFydE5lZWRlZDsKCglwcm90ZWN0ZWQgdHJhbnNpZW50IE1hcCBtb2R1bGVTdGF0ZSA9IG5ldyBIYXNoTWFwKCk7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IE1hcCBtb2R1bGVQdWJsaXNoU3RhdGUgPSBuZXcgSGFzaE1hcCgpOwoJcHJvdGVjdGVkIHRyYW5zaWVudCBNYXAgbW9kdWxlUmVzdGFydFN0YXRlID0gbmV3IEhhc2hNYXAoKTsKCQoJcHJvdGVjdGVkIHRyYW5zaWVudCBJU3RhdHVzIHNlcnZlclN0YXR1czsKCXByb3RlY3RlZCB0cmFuc2llbnQgTWFwIG1vZHVsZVN0YXR1cyA9IG5ldyBIYXNoTWFwKCk7CgoJcHJvdGVjdGVkIHRyYW5zaWVudCBTZXJ2ZXJQdWJsaXNoSW5mbyBwdWJsaXNoSW5mbzsKCXByb3RlY3RlZCB0cmFuc2llbnQgQXV0b1B1Ymxpc2hUaHJlYWQgYXV0b1B1Ymxpc2hUaHJlYWQ7CgovKglwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmdbXSBzdGF0ZVN0cmluZ3MgPSBuZXcgU3RyaW5nW10gewoJCSJ1bmtub3duIiwgInN0YXJ0aW5nIiwgInN0YXJ0ZWQiLCAic3RhcnRlZF9kZWJ1ZyIsCgkJInN0b3BwaW5nIiwgInN0b3BwZWQiLCAic3RhcnRlZF91bnN1cHBvcnRlZCIsICJzdGFydGVkX3Byb2ZpbGUiCgl9OyovCgkKCS8vIHB1Ymxpc2ggbGlzdGVuZXJzCglwcm90ZWN0ZWQgdHJhbnNpZW50IExpc3QgcHVibGlzaExpc3RlbmVyczsKCQoJLy8gU2VydmVyIGxpc3RlbmVycwoJcHJvdGVjdGVkIHRyYW5zaWVudCBTZXJ2ZXJOb3RpZmljYXRpb25NYW5hZ2VyIG5vdGlmaWNhdGlvbk1hbmFnZXI7CgkKCXB1YmxpYyBjbGFzcyBBdXRvUHVibGlzaFRocmVhZCBleHRlbmRzIFRocmVhZCB7CgkJcHVibGljIGJvb2xlYW4gc3RvcDsKCQlwdWJsaWMgaW50IHRpbWUgPSAwOyAKCQkKCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkF1dG8tcHVibGlzaCB0aHJlYWQgc3RhcnRpbmcgZm9yICIgKyBTZXJ2ZXIudGhpcyArICIgLSAiICsgdGltZSArICJzIik7CgkJCWlmIChzdG9wKQoJCQkJcmV0dXJuOwoJCQkKCQkJdHJ5IHsKCQkJCXNsZWVwKHRpbWUgKiAxMDAwKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCS8vIGlnbm9yZQoJCQl9CgkJCQoJCQlpZiAoc3RvcCkKCQkJCXJldHVybjsKCQkJCgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkF1dG8tcHVibGlzaCB0aHJlYWQgcHVibGlzaGluZyAiICsgU2VydmVyLnRoaXMpOwoKCQkJUHVibGlzaFNlcnZlckpvYiBwdWJsaXNoSm9iID0gbmV3IFB1Ymxpc2hTZXJ2ZXJKb2IoU2VydmVyLnRoaXMsIElTZXJ2ZXIuUFVCTElTSF9BVVRPLCBmYWxzZSk7CgkJCXB1Ymxpc2hKb2Iuc2NoZWR1bGUoKTsKCQl9Cgl9CgoJLy8gd29ya2luZyBjb3B5LCBsb2FkZWQgcmVzb3VyY2UKCXB1YmxpYyBTZXJ2ZXIoSUZpbGUgZmlsZSkgewoJCXN1cGVyKGZpbGUpOwoJCW1hcC5wdXQoUFJPUF9IT1NUTkFNRSwgImxvY2FsaG9zdCIpOwoJfQoKCS8vIGNyZWF0aW9uICh3b3JraW5nIGNvcHkpCglwdWJsaWMgU2VydmVyKFN0cmluZyBpZCwgSUZpbGUgZmlsZSwgSVJ1bnRpbWUgcnVudGltZSwgSVNlcnZlclR5cGUgc2VydmVyVHlwZSkgewoJCXN1cGVyKGZpbGUsIGlkKTsKCQl0aGlzLnJ1bnRpbWUgPSBydW50aW1lOwoJCXRoaXMuc2VydmVyVHlwZSA9IHNlcnZlclR5cGU7CgkJbWFwLnB1dCgic2VydmVyLXR5cGUtaWQiLCBzZXJ2ZXJUeXBlLmdldElkKCkpOwoJCW1hcC5wdXQoUFJPUF9IT1NUTkFNRSwgImxvY2FsaG9zdCIpOwoJCWlmIChydW50aW1lICE9IG51bGwgJiYgcnVudGltZS5nZXRSdW50aW1lVHlwZSgpICE9IG51bGwpIHsKCQkJU3RyaW5nIG5hbWUgPSBydW50aW1lLmdldFJ1bnRpbWVUeXBlKCkuZ2V0TmFtZSgpOwoJCQltYXAucHV0KFBST1BfTkFNRSwgbmFtZSk7CgkJfQoJCXNlcnZlclN0YXRlID0gKChTZXJ2ZXJUeXBlKXNlcnZlclR5cGUpLmdldEluaXRpYWxTdGF0ZSgpOwoJfQoJCglwdWJsaWMgSVNlcnZlclR5cGUgZ2V0U2VydmVyVHlwZSgpIHsKCQlyZXR1cm4gc2VydmVyVHlwZTsKCX0KCQoJcHVibGljIElTZXJ2ZXJXb3JraW5nQ29weSBjcmVhdGVXb3JraW5nQ29weSgpIHsKCQlyZXR1cm4gbmV3IFNlcnZlcldvcmtpbmdDb3B5KHRoaXMpOyAKCX0KCglwdWJsaWMgYm9vbGVhbiBpc1dvcmtpbmdDb3B5KCkgewoJCXJldHVybiBmYWxzZTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgZGVsZXRlRnJvbU1ldGFkYXRhKCkgewoJCVJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpLnJlbW92ZVNlcnZlcih0aGlzKTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgc2F2ZVRvTWV0YWRhdGEoSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJc3VwZXIuc2F2ZVRvTWV0YWRhdGEobW9uaXRvcik7CgkJUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCkuYWRkU2VydmVyKHRoaXMpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgY29tLmlibS53dHAuc2VydmVyLmNvcmUuSVNlcnZlcjIjZ2V0UnVudGltZSgpCgkgKi8KCXB1YmxpYyBJUnVudGltZSBnZXRSdW50aW1lKCkgewoJCXJldHVybiBydW50aW1lOwoJfQoKCXByb3RlY3RlZCBTdHJpbmcgZ2V0UnVudGltZUlkKCkgewoJCXJldHVybiBnZXRBdHRyaWJ1dGUoUlVOVElNRV9JRCwgKFN0cmluZykgbnVsbCk7Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBjb20uaWJtLnd0cC5zZXJ2ZXIuY29yZS5JU2VydmVyMiNnZXRTZXJ2ZXJDb25maWd1cmF0aW9uKCkKCSAqLwoJcHVibGljIElGb2xkZXIgZ2V0U2VydmVyQ29uZmlndXJhdGlvbigpIHsKCQlyZXR1cm4gY29uZmlndXJhdGlvbjsKCX0KCglwcm90ZWN0ZWQgU2VydmVyRGVsZWdhdGUgZ2V0RGVsZWdhdGUoKSB7CgkJaWYgKGRlbGVnYXRlICE9IG51bGwpCgkJCXJldHVybiBkZWxlZ2F0ZTsKCQkKCQlpZiAoc2VydmVyVHlwZSAhPSBudWxsKSB7CgkJCXN5bmNocm9uaXplZCAodGhpcykgewoJCQkJaWYgKGRlbGVnYXRlID09IG51bGwpIHsKCQkJCQlKb2Igam9iID0gbmV3IEpvYigiTG9hZCBkZWxlZ2F0ZSIpIHsKCQkJCQkJcHJvdGVjdGVkIElTdGF0dXMgcnVuKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCQkJCQkJdHJ5IHsKCQkJCQkJCQlsb25nIHRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQkJCQlJQ29uZmlndXJhdGlvbkVsZW1lbnQgZWxlbWVudCA9ICgoU2VydmVyVHlwZSkgc2VydmVyVHlwZSkuZ2V0RWxlbWVudCgpOwoJCQkJCQkJCWRlbGVnYXRlID0gKFNlcnZlckRlbGVnYXRlKSBlbGVtZW50LmNyZWF0ZUV4ZWN1dGFibGVFeHRlbnNpb24oImNsYXNzIik7CgkJCQkJCQkJZGVsZWdhdGUuaW5pdGlhbGl6ZShTZXJ2ZXIudGhpcyk7CgkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuUEVSRk9STUFOQ0UsICJTZXJ2ZXIuZ2V0RGVsZWdhdGUoKTogPCIgKyAoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCkgLSB0aW1lKSArICI+ICIgKyBnZXRTZXJ2ZXJUeXBlKCkuZ2V0SWQoKSk7CgkJCQkJCQl9IGNhdGNoIChUaHJvd2FibGUgdCkgewoJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkNvdWxkIG5vdCBjcmVhdGUgZGVsZWdhdGUgIiArIHRvU3RyaW5nKCksIHQpOwoJCQkJCQkJfQoJCQkJCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgIiIsIG51bGwpOwoJCQkJCQl9CgkJCQkJfTsKCQkJCQlqb2Iuc2NoZWR1bGUoKTsKCQkJCQl0cnkgewoJCQkJCQlqb2Iuam9pbigpOwoJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCS8vIGlnbm9yZQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gZGVsZWdhdGU7Cgl9CgkKCXByb3RlY3RlZCBTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZSBnZXRCZWhhdmlvdXJEZWxlZ2F0ZSgpIHsKCQlpZiAoYmVoYXZpb3VyRGVsZWdhdGUgIT0gbnVsbCkKCQkJcmV0dXJuIGJlaGF2aW91ckRlbGVnYXRlOwoJCQoJCWlmIChzZXJ2ZXJUeXBlICE9IG51bGwpIHsKCQkJc3luY2hyb25pemVkICh0aGlzKSB7CgkJCQlpZiAoYmVoYXZpb3VyRGVsZWdhdGUgPT0gbnVsbCkgewoJCQkJCUpvYiBqb2IgPSBuZXcgSm9iKCJMb2FkIGRlbGVnYXRlIikgewoJCQkJCQlwcm90ZWN0ZWQgSVN0YXR1cyBydW4oSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJCQkJCQl0cnkgewoJCQkJCQkJCWxvbmcgdGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCQkJCUlDb25maWd1cmF0aW9uRWxlbWVudCBlbGVtZW50ID0gKChTZXJ2ZXJUeXBlKSBzZXJ2ZXJUeXBlKS5nZXRFbGVtZW50KCk7CgkJCQkJCQkJYmVoYXZpb3VyRGVsZWdhdGUgPSAoU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUpIGVsZW1lbnQuY3JlYXRlRXhlY3V0YWJsZUV4dGVuc2lvbigiYmVoYXZpb3VyQ2xhc3MiKTsKCQkJCQkJCQliZWhhdmlvdXJEZWxlZ2F0ZS5pbml0aWFsaXplKFNlcnZlci50aGlzKTsKCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5QRVJGT1JNQU5DRSwgIlNlcnZlci5nZXRCZWhhdmlvdXJEZWxlZ2F0ZSgpOiA8IiArIChTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSAtIHRpbWUpICsgIj4gIiArIGdldFNlcnZlclR5cGUoKS5nZXRJZCgpKTsKCQkJCQkJCX0gY2F0Y2ggKFRocm93YWJsZSB0KSB7CgkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IGNyZWF0ZSBiZWhhdmlvdXIgZGVsZWdhdGUgIiArIHRvU3RyaW5nKCksIHQpOwoJCQkJCQkJfQoJCQkJCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgIiIsIG51bGwpOwoJCQkJCQl9CgkJCQkJfTsKCQkJCQlqb2Iuc2NoZWR1bGUoKTsKCQkJCQl0cnkgewoJCQkJCQlqb2Iuam9pbigpOwoJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCS8vIGlnbm9yZQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gYmVoYXZpb3VyRGVsZWdhdGU7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGRlbGVnYXRlIGhhcyBiZWVuIGxvYWRlZC4KCSAqIAoJICogQHJldHVybiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgZGVsZWdhdGUgaGFzIGJlZW4gbG9hZGVkLCBhbmQKCSAqICAgIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqLwoJcHVibGljIGJvb2xlYW4gaXNEZWxlZ2F0ZUxvYWRlZCgpIHsKCQlyZXR1cm4gZGVsZWdhdGUgIT0gbnVsbDsKCX0KCQoJcHVibGljIHZvaWQgZGlzcG9zZSgpIHsKCQlpZiAoZGVsZWdhdGUgIT0gbnVsbCkKCQkJZGVsZWdhdGUuZGlzcG9zZSgpOwoJfQoKCXB1YmxpYyBTdHJpbmcgZ2V0SG9zdCgpIHsKCQlyZXR1cm4gZ2V0QXR0cmlidXRlKFBST1BfSE9TVE5BTUUsICJsb2NhbGhvc3QiKTsKCX0KCQoJcHVibGljIGludCBnZXRBdXRvUHVibGlzaFRpbWUoKSB7CgkJcmV0dXJuIGdldEF0dHJpYnV0ZShQUk9QX0FVVE9fUFVCTElTSF9USU1FLCAtMSk7Cgl9CgkKCXB1YmxpYyBib29sZWFuIGdldEF1dG9QdWJsaXNoRGVmYXVsdCgpIHsKCQlyZXR1cm4gZ2V0QXR0cmlidXRlKFBST1BfQVVUT19QVUJMSVNIX0RFRkFVTFQsIHRydWUpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgc2VydmVyLiAoc2VlIFNFUlZFUl9YWFggY29uc3RhbnRzKQoJICoKCSAqIEByZXR1cm4gaW50CgkgKi8KCXB1YmxpYyBpbnQgZ2V0U2VydmVyU3RhdGUoKSB7CgkJcmV0dXJuIHNlcnZlclN0YXRlOwoJfQoJCglwdWJsaWMgU3RyaW5nIGdldE1vZGUoKSB7CgkJcmV0dXJuIG1vZGU7Cgl9CgoJcHVibGljIHZvaWQgc2V0U2VydmVyU3RhdGUoaW50IHN0YXRlKSB7CgkJaWYgKHN0YXRlID09IHNlcnZlclN0YXRlKQoJCQlyZXR1cm47CgoJCXRoaXMuc2VydmVyU3RhdGUgPSBzdGF0ZTsKCQlmaXJlU2VydmVyU3RhdGVDaGFuZ2VFdmVudCgpOwoJfQoJCgkvKioKCSAqIEFkZCBhIGxpc3RlbmVyIHRvIHRoaXMgc2VydmVyLgoJICoKCSAqIEBwYXJhbSBsaXN0ZW5lciBvcmcuZWNsaXBzZS53c3Quc2VydmVyLm1vZGVsLklTZXJ2ZXJMaXN0ZW5lcgoJICovCglwdWJsaWMgdm9pZCBhZGRTZXJ2ZXJMaXN0ZW5lcihJU2VydmVyTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICJBZGRpbmcgc2VydmVyIGxpc3RlbmVyICIgKyBsaXN0ZW5lciArICIgdG8gIiArIHRoaXMpOwoJCWdldFNlcnZlck5vdGlmaWNhdGlvbk1hbmFnZXIoKS5hZGRMaXN0ZW5lcihsaXN0ZW5lcik7Cgl9CgkKCS8qKgoJICogQWRkIGEgbGlzdGVuZXIgdG8gdGhpcyBzZXJ2ZXIgd2l0aCB0aGUgZ2l2ZW4gZXZlbnQgbWFzay4KCSAqCgkgKiBAcGFyYW0gbGlzdGVuZXIgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5tb2RlbC5JU2VydmVyTGlzdGVuZXIKCSAqIEBwYXJhbSBldmVudE1hc2sgdG8gbGltaXQgbGlzdGVuaW5nIHRvIGNlcnRhaW4gdHlwZXMgb2YgZXZlbnRzCgkgKi8KCXB1YmxpYyB2b2lkIGFkZFNlcnZlckxpc3RlbmVyKElTZXJ2ZXJMaXN0ZW5lciBsaXN0ZW5lciwgaW50IGV2ZW50TWFzaykgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkxJU1RFTkVSUywgIkFkZGluZyBzZXJ2ZXIgbGlzdGVuZXIgIiArIGxpc3RlbmVyICsgIiB0byAiICsgdGhpcyArICIgd2l0aCBldmVudE1hc2sgIiArIGV2ZW50TWFzayk7CgkJZ2V0U2VydmVyTm90aWZpY2F0aW9uTWFuYWdlcigpLmFkZExpc3RlbmVyKGxpc3RlbmVyLCBldmVudE1hc2spOwoJfQoKCS8qKgoJICogUmVtb3ZlIGEgbGlzdGVuZXIgZnJvbSB0aGlzIHNlcnZlci4KCSAqCgkgKiBAcGFyYW0gbGlzdGVuZXIgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5tb2RlbC5JU2VydmVyTGlzdGVuZXIKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlU2VydmVyTGlzdGVuZXIoSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiUmVtb3Zpbmcgc2VydmVyIGxpc3RlbmVyICIgKyBsaXN0ZW5lciArICIgZnJvbSAiICsgdGhpcyk7CgkJZ2V0U2VydmVyTm90aWZpY2F0aW9uTWFuYWdlcigpLnJlbW92ZUxpc3RlbmVyKGxpc3RlbmVyKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIHJlc3RhcnQgc3RhdGUgY2hhbmdlIGV2ZW50LgoJICovCglwcm90ZWN0ZWQgdm9pZCBmaXJlUmVzdGFydFN0YXRlQ2hhbmdlRXZlbnQoKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiLT4tIEZpcmluZyBzZXJ2ZXIgcmVzdGFydCBjaGFuZ2UgZXZlbnQ6ICIgKyBnZXROYW1lKCkgKyAiIC0+LSIpOwoJCgkJaWYgKG5vdGlmaWNhdGlvbk1hbmFnZXIgPT0gbnVsbCB8fCBub3RpZmljYXRpb25NYW5hZ2VyLmhhc0xpc3RlbmVyRW50cmllcygpKQoJCQlyZXR1cm47CgkKCQlub3RpZmljYXRpb25NYW5hZ2VyLmJyb2FkY2FzdENoYW5nZSgKCQkJbmV3IFNlcnZlckV2ZW50KFNlcnZlckV2ZW50LlNFUlZFUl9DSEFOR0UgfCBTZXJ2ZXJFdmVudC5SRVNUQVJUX1NUQVRFX0NIQU5HRSwgdGhpcywgZ2V0U2VydmVyU3RhdGUoKSwgCgkJCQlnZXRTZXJ2ZXJQdWJsaXNoU3RhdGUoKSwgZ2V0U2VydmVyUmVzdGFydFN0YXRlKCkpKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIHN0YXRlIGNoYW5nZSBldmVudC4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmlyZVNlcnZlclN0YXRlQ2hhbmdlRXZlbnQoKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiLT4tIEZpcmluZyBzZXJ2ZXIgc3RhdGUgY2hhbmdlIGV2ZW50OiAiICsgZ2V0TmFtZSgpICsgIiwgIiArIGdldFNlcnZlclN0YXRlKCkgKyAiIC0+LSIpOwoJCgkJaWYgKG5vdGlmaWNhdGlvbk1hbmFnZXIgPT0gbnVsbCB8fCBub3RpZmljYXRpb25NYW5hZ2VyLmhhc0xpc3RlbmVyRW50cmllcygpKQoJCQlyZXR1cm47CgkKCQlub3RpZmljYXRpb25NYW5hZ2VyLmJyb2FkY2FzdENoYW5nZSgKCQkJbmV3IFNlcnZlckV2ZW50KFNlcnZlckV2ZW50LlNFUlZFUl9DSEFOR0UgfCBTZXJ2ZXJFdmVudC5TVEFURV9DSEFOR0UsIHRoaXMsIGdldFNlcnZlclN0YXRlKCksIAoJCQkJZ2V0U2VydmVyUHVibGlzaFN0YXRlKCksIGdldFNlcnZlclJlc3RhcnRTdGF0ZSgpKSk7Cgl9CgoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIG1vZHVsZSBzdGF0ZSBjaGFuZ2UgZXZlbnQuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpcmVTZXJ2ZXJNb2R1bGVTdGF0ZUNoYW5nZUV2ZW50KElNb2R1bGVbXSBtb2R1bGUpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICItPi0gRmlyaW5nIHNlcnZlciBtb2R1bGUgc3RhdGUgY2hhbmdlIGV2ZW50OiAiICsgZ2V0TmFtZSgpICsgIiwgIiArIGdldFNlcnZlclN0YXRlKCkgKyAiIC0+LSIpOwoJCQoJCWlmIChub3RpZmljYXRpb25NYW5hZ2VyID09IG51bGwgfHwgbm90aWZpY2F0aW9uTWFuYWdlci5oYXNMaXN0ZW5lckVudHJpZXMoKSkKCQkJcmV0dXJuOwoJCgkJbm90aWZpY2F0aW9uTWFuYWdlci5icm9hZGNhc3RDaGFuZ2UoCgkJCW5ldyBTZXJ2ZXJFdmVudChTZXJ2ZXJFdmVudC5NT0RVTEVfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFLCB0aGlzLCBtb2R1bGUsIGdldE1vZHVsZVN0YXRlKG1vZHVsZSksIAoJCQkJZ2V0TW9kdWxlUHVibGlzaFN0YXRlKG1vZHVsZSksIGdldE1vZHVsZVJlc3RhcnRTdGF0ZShtb2R1bGUpKSk7Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kZShTdHJpbmcgbSkgewoJCXRoaXMubW9kZSA9IG07Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kdWxlU3RhdGUoSU1vZHVsZVtdIG1vZHVsZSwgaW50IHN0YXRlKSB7CgkJSW50ZWdlciBpbiA9IG5ldyBJbnRlZ2VyKHN0YXRlKTsKCQltb2R1bGVTdGF0ZS5wdXQoZ2V0S2V5KG1vZHVsZSksIGluKTsKCQlmaXJlU2VydmVyTW9kdWxlU3RhdGVDaGFuZ2VFdmVudChtb2R1bGUpOwoJfQoJCglwdWJsaWMgdm9pZCBzZXRNb2R1bGVQdWJsaXNoU3RhdGUoSU1vZHVsZVtdIG1vZHVsZSwgaW50IHN0YXRlKSB7CgkJSW50ZWdlciBpbiA9IG5ldyBJbnRlZ2VyKHN0YXRlKTsKCQltb2R1bGVQdWJsaXNoU3RhdGUucHV0KGdldEtleShtb2R1bGUpLCBpbik7CgkJLy9maXJlU2VydmVyTW9kdWxlU3RhdGVDaGFuZ2VFdmVudChtb2R1bGUpOwoJfQoKCXB1YmxpYyB2b2lkIHNldE1vZHVsZVJlc3RhcnRTdGF0ZShJTW9kdWxlW10gbW9kdWxlLCBib29sZWFuIHIpIHsKCQlCb29sZWFuIGIgPSBuZXcgQm9vbGVhbihyKTsKCQltb2R1bGVTdGF0ZS5wdXQoZ2V0S2V5KG1vZHVsZSksIGIpOwoJCS8vZmlyZVNlcnZlck1vZHVsZVN0YXRlQ2hhbmdlRXZlbnQobW9kdWxlKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCBoYW5kbGVNb2R1bGVQcm9qZWN0Q2hhbmdlKGZpbmFsIElNb2R1bGUgbW9kdWxlKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiPiBoYW5kbGVEZXBsb3lhYmxlUHJvamVjdENoYW5nZSgpICIgKyB0aGlzICsgIiAiICsgbW9kdWxlKTsKCQkKCQljbGFzcyBIZWxwZXIgewoJCQlib29sZWFuIGNoYW5nZWQ7CgkJfQoJCWZpbmFsIEhlbHBlciBoZWxwZXIgPSBuZXcgSGVscGVyKCk7CgkJCgkJSU1vZHVsZVZpc2l0b3IgdmlzaXRvciA9IG5ldyBJTW9kdWxlVmlzaXRvcigpIHsKCQkJcHVibGljIGJvb2xlYW4gdmlzaXQoSU1vZHVsZVtdIG1vZHVsZTIpIHsKCQkJCWludCBzaXplID0gbW9kdWxlMi5sZW5ndGg7CgkJCQlJTW9kdWxlIG0gPSBtb2R1bGUyW3NpemUgLSAxXTsKCQkJCWlmIChtLmdldFByb2plY3QoKSA9PSBudWxsKQoJCQkJCXJldHVybiB0cnVlOwoJCQkJCgkJCQlpZiAobW9kdWxlLmVxdWFscyhtKSkgewoJCQkJCUlNb2R1bGVSZXNvdXJjZURlbHRhW10gZGVsdGEyID0gZ2V0UHVibGlzaGVkUmVzb3VyY2VEZWx0YShtb2R1bGUyKTsKCQkJCQlpZiAoZGVsdGEyLmxlbmd0aCA+IDApCgkJCQkJCWhlbHBlci5jaGFuZ2VkID0gdHJ1ZTsKCQkJCQkKCQkJCQkvLyBUT0RPCgkJCQkJLyppZiAoZGVwbG95YWJsZURlbHRhW2ldID09IG51bGwpCgkJCQkJCWRlcGxveWFibGVEZWx0YVtpXSA9IG1vZHVsZVByb2plY3RzW2ldLmdldE1vZHVsZVJlc291cmNlRGVsdGEoZGVsdGEpOwoJCQkJCQoJCQkJCWlmIChkZXBsb3lhYmxlRGVsdGFbaV0gIT0gbnVsbCkgewoJCQkJCQkvLyB1cGRhdGVEZXBsb3lhYmxlKG1vZHVsZSwgZGVwbG95YWJsZURlbHRhW2ldKTsKCgkJCQkJCU1vZHVsZVB1Ymxpc2hJbmZvIGNvbnRyb2wgPSBQdWJsaXNoSW5mby5nZXRQdWJsaXNoSW5mbygpLmdldFB1Ymxpc2hDb250cm9sKFNlcnZlci50aGlzLCBwYXJlbnRzLCBtb2R1bGUpOwoJCQkJCQlpZiAoY29udHJvbC5pc0RpcnR5KCkpCgkJCQkJCQlyZXR1cm4gdHJ1ZTsKCQoJCQkJCQljb250cm9sLnNldERpcnR5KHRydWUpOwoJCQkJCQlmaXJlUHVibGlzaFN0YXRlQ2hhbmdlKHBhcmVudHMsIG1vZHVsZSk7CgkJCQkJfSovCgkJCQkJcmV0dXJuIHRydWU7CgkJCQl9CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX07CgoJCXZpc2l0KHZpc2l0b3IsIG51bGwpOwoJCQoJCWlmICghaGVscGVyLmNoYW5nZWQpCgkJCXJldHVybjsKCQkKCQkvLyBjaGVjayBmb3IgYXV0by1wdWJsaXNoCgkJaWYgKGF1dG9QdWJsaXNoVGhyZWFkICE9IG51bGwpIHsKCQkJYXV0b1B1Ymxpc2hUaHJlYWQuc3RvcCA9IHRydWU7CgkJCWF1dG9QdWJsaXNoVGhyZWFkLmludGVycnVwdCgpOwoJCQlhdXRvUHVibGlzaFRocmVhZCA9IG51bGw7CgkJfQoJCQoJCWludCB0aW1lID0gMDsKCQlpZiAoZ2V0QXV0b1B1Ymxpc2hEZWZhdWx0KCkpIHsKCQkJYm9vbGVhbiBsb2NhbCA9IFNvY2tldFV0aWwuaXNMb2NhbGhvc3QoZ2V0SG9zdCgpKTsKCQkJaWYgKGxvY2FsICYmIFNlcnZlclByZWZlcmVuY2VzLmdldEluc3RhbmNlKCkuZ2V0QXV0b1B1Ymxpc2hMb2NhbCgpKQoJCQkJdGltZSA9IFNlcnZlclByZWZlcmVuY2VzLmdldEluc3RhbmNlKCkuZ2V0QXV0b1B1Ymxpc2hMb2NhbFRpbWUoKTsKCQkJZWxzZSBpZiAoIWxvY2FsICYmIFNlcnZlclByZWZlcmVuY2VzLmdldEluc3RhbmNlKCkuZ2V0QXV0b1B1Ymxpc2hSZW1vdGUoKSkKCQkJCXRpbWUgPSBTZXJ2ZXJQcmVmZXJlbmNlcy5nZXRJbnN0YW5jZSgpLmdldEF1dG9QdWJsaXNoUmVtb3RlVGltZSgpOwoJCX0gZWxzZSB7CgkJCXRpbWUgPSBnZXRBdXRvUHVibGlzaFRpbWUoKTsKCQl9CgkJCgkJaWYgKHRpbWUgPiA1KSB7CgkJCWF1dG9QdWJsaXNoVGhyZWFkID0gbmV3IEF1dG9QdWJsaXNoVGhyZWFkKCk7CgkJCWF1dG9QdWJsaXNoVGhyZWFkLnRpbWUgPSB0aW1lOwoJCQlhdXRvUHVibGlzaFRocmVhZC5zZXRQcmlvcml0eShUaHJlYWQuTUlOX1BSSU9SSVRZICsgMSk7CgkJCWF1dG9QdWJsaXNoVGhyZWFkLnN0YXJ0KCk7CgkJfQoJCQoJCS8vVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiPCBoYW5kbGVEZXBsb3lhYmxlUHJvamVjdENoYW5nZSgpIik7Cgl9CgkKCXByaXZhdGUgU2VydmVyTm90aWZpY2F0aW9uTWFuYWdlciBnZXRTZXJ2ZXJOb3RpZmljYXRpb25NYW5hZ2VyKCkgewoJCWlmIChub3RpZmljYXRpb25NYW5hZ2VyID09IG51bGwpIHsKCQkJbm90aWZpY2F0aW9uTWFuYWdlciA9IG5ldyBTZXJ2ZXJOb3RpZmljYXRpb25NYW5hZ2VyKCk7CgkJfQoJCXJldHVybiBub3RpZmljYXRpb25NYW5hZ2VyOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgY29uZmlndXJhdGlvbidzIHN5bmMgc3RhdGUuCgkgKgoJICogQHJldHVybiBpbnQKCSAqLwoJcHVibGljIGludCBnZXRTZXJ2ZXJQdWJsaXNoU3RhdGUoKSB7CgkJcmV0dXJuIHNlcnZlclN5bmNTdGF0ZTsKCX0KCgkvKioKCSAqIFNldHMgdGhlIGNvbmZpZ3VyYXRpb24gc3luYyBzdGF0ZS4KCSAqCgkgKiBAcGFyYW0gc3RhdGUgaW50CgkgKi8KCXB1YmxpYyB2b2lkIHNldFNlcnZlclB1Ymxpc2hTdGF0ZShpbnQgc3RhdGUpIHsKCQlpZiAoc3RhdGUgPT0gc2VydmVyU3luY1N0YXRlKQoJCQlyZXR1cm47CgkJc2VydmVyU3luY1N0YXRlID0gc3RhdGU7CgkJLy9maXJlQ29uZmlndXJhdGlvblN5bmNTdGF0ZUNoYW5nZUV2ZW50KCk7Cgl9CgoJLyoqCgkgKiBBZGRzIGEgcHVibGlzaCBsaXN0ZW5lciB0byB0aGlzIHNlcnZlci4KCSAqIEhhcyBubyBlZmZlY3QgaWYgYW4gaWRlbnRpY2FsIGxpc3RlbmVyIGlzIGFscmVhZHkgcmVnaXN0ZXJlZC4KCSAqCgkgKiBAcGFyYW0gbGlzdGVuZXIgdGhlIHB1Ymxpc2ggbGlzdGVuZXIKCSAqIEBzZWUgI3JlbW92ZVB1Ymxpc2hMaXN0ZW5lcihJUHVibGlzaExpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCBhZGRQdWJsaXNoTGlzdGVuZXIoSVB1Ymxpc2hMaXN0ZW5lciBsaXN0ZW5lcikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkxJU1RFTkVSUywgIkFkZGluZyBwdWJsaXNoIGxpc3RlbmVyICIgKyBsaXN0ZW5lciArICIgdG8gIiArIHRoaXMpOwoKCQlpZiAocHVibGlzaExpc3RlbmVycyA9PSBudWxsKQoJCQlwdWJsaXNoTGlzdGVuZXJzID0gbmV3IEFycmF5TGlzdCgpOwoJCXB1Ymxpc2hMaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTsKCX0KCgkvKioKCSAqIFJlbW92ZXMgYSBwdWJsaXNoIGxpc3RlbmVyIGZyb20gdGhpcyBzZXJ2ZXIuCgkgKiBIYXMgbm8gZWZmZWN0IGlmIHRoZSBsaXN0ZW5lciBpcyBub3QgcmVnaXN0ZXJlZC4KCSAqCgkgKiBAcGFyYW0gbGlzdGVuZXIgdGhlIHB1Ymxpc2ggbGlzdGVuZXIKCSAqIEBzZWUgI2FkZFB1Ymxpc2hMaXN0ZW5lcihJUHVibGlzaExpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQdWJsaXNoTGlzdGVuZXIoSVB1Ymxpc2hMaXN0ZW5lciBsaXN0ZW5lcikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkxJU1RFTkVSUywgIlJlbW92aW5nIHB1Ymxpc2ggbGlzdGVuZXIgIiArIGxpc3RlbmVyICsgIiBmcm9tICIgKyB0aGlzKTsKCgkJaWYgKHB1Ymxpc2hMaXN0ZW5lcnMgIT0gbnVsbCkKCQkJcHVibGlzaExpc3RlbmVycy5yZW1vdmUobGlzdGVuZXIpOwoJfQoJCgkvKioKCSAqIEZpcmUgYSBwdWJsaXNoIHN0YXJ0IGV2ZW50LgoJICovCglwcml2YXRlIHZvaWQgZmlyZVB1Ymxpc2hTdGFydGVkKCkgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0+LSBGaXJpbmcgcHVibGlzaCBzdGFydGVkIGV2ZW50IC0+LSIpOwoJCgkJaWYgKHB1Ymxpc2hMaXN0ZW5lcnMgPT0gbnVsbCB8fCBwdWJsaXNoTGlzdGVuZXJzLmlzRW1wdHkoKSkKCQkJcmV0dXJuOwoKCQlpbnQgc2l6ZSA9IHB1Ymxpc2hMaXN0ZW5lcnMuc2l6ZSgpOwoJCUlQdWJsaXNoTGlzdGVuZXJbXSBzcmwgPSBuZXcgSVB1Ymxpc2hMaXN0ZW5lcltzaXplXTsKCQlwdWJsaXNoTGlzdGVuZXJzLnRvQXJyYXkoc3JsKTsKCgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiICBGaXJpbmcgcHVibGlzaCBzdGFydGVkIGV2ZW50IHRvICIgKyBzcmxbaV0pOwoJCQl0cnkgewoJCQkJc3JsW2ldLnB1Ymxpc2hTdGFydGVkKHRoaXMpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgcHVibGlzaCBzdGFydGVkIGV2ZW50IHRvICIgKyBzcmxbaV0sIGUpOwoJCQl9CgkJfQoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItPC0gRG9uZSBmaXJpbmcgcHVibGlzaCBzdGFydGVkIGV2ZW50IC08LSIpOwoJfQoJCgkvKioKCSAqIEZpcmUgYSBwdWJsaXNoIHRhcmdldCBldmVudC4KCSAqCgkgKiBAcGFyYW0gbW9kdWxlIHRoZSBmaXJpbmcgbW9kdWxlCgkgKi8KCXByaXZhdGUgdm9pZCBmaXJlTW9kdWxlUHVibGlzaFN0YXJ0ZWQoSU1vZHVsZVtdIG1vZHVsZSkgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0+LSBGaXJpbmcgbW9kdWxlIHB1Ymxpc2ggc3RhcnRlZCBldmVudDogIiArIG1vZHVsZSArICIgLT4tIik7CgkKCQlpZiAocHVibGlzaExpc3RlbmVycyA9PSBudWxsIHx8IHB1Ymxpc2hMaXN0ZW5lcnMuaXNFbXB0eSgpKQoJCQlyZXR1cm47CgoJCWludCBzaXplID0gcHVibGlzaExpc3RlbmVycy5zaXplKCk7CgkJSVB1Ymxpc2hMaXN0ZW5lcltdIHNybCA9IG5ldyBJUHVibGlzaExpc3RlbmVyW3NpemVdOwoJCXB1Ymxpc2hMaXN0ZW5lcnMudG9BcnJheShzcmwpOwoKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICIgIEZpcmluZyBtb2R1bGUgcHVibGlzaCBzdGFydGVkIGV2ZW50IHRvICIgKyBzcmxbaV0pOwoJCQl0cnkgewoJCQkJc3JsW2ldLnB1Ymxpc2hNb2R1bGVTdGFydGVkKHRoaXMsIG1vZHVsZSk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICIgIEVycm9yIGZpcmluZyBtb2R1bGUgcHVibGlzaCBzdGFydGVkIGV2ZW50IHRvICIgKyBzcmxbaV0sIGUpOwoJCQl9CgkJfQoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItPC0gRG9uZSBmaXJpbmcgbW9kdWxlIHB1Ymxpc2ggc3RhcnRlZCBldmVudCAtPC0iKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgcHVibGlzaCB0YXJnZXQgZXZlbnQuCgkgKgoJICogQHBhcmFtIG1vZHVsZSB0aGUgZmlyaW5nIG1vZHVsZQoJICogQHBhcmFtIHN0YXR1cyBwdWJsaXNoaW5nIHN0YXR1cwoJICovCglwcml2YXRlIHZvaWQgZmlyZU1vZHVsZVB1Ymxpc2hGaW5pc2hlZChJTW9kdWxlW10gbW9kdWxlLCBJU3RhdHVzIHN0YXR1cykgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0+LSBGaXJpbmcgbW9kdWxlIGZpbmlzaGVkIGV2ZW50OiAiICsgbW9kdWxlICsgIiAiICsgc3RhdHVzICsgIiAtPi0iKTsKCQoJCWlmIChwdWJsaXNoTGlzdGVuZXJzID09IG51bGwgfHwgcHVibGlzaExpc3RlbmVycy5pc0VtcHR5KCkpCgkJCXJldHVybjsKCgkJaW50IHNpemUgPSBwdWJsaXNoTGlzdGVuZXJzLnNpemUoKTsKCQlJUHVibGlzaExpc3RlbmVyW10gc3JsID0gbmV3IElQdWJsaXNoTGlzdGVuZXJbc2l6ZV07CgkJcHVibGlzaExpc3RlbmVycy50b0FycmF5KHNybCk7CgoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIiAgRmlyaW5nIG1vZHVsZSBmaW5pc2hlZCBldmVudCB0byAiICsgc3JsW2ldKTsKCQkJdHJ5IHsKCQkJCXNybFtpXS5wdWJsaXNoTW9kdWxlRmluaXNoZWQodGhpcywgbW9kdWxlLCBzdGF0dXMpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgbW9kdWxlIGZpbmlzaGVkIGV2ZW50IHRvICIgKyBzcmxbaV0sIGUpOwoJCQl9CgkJfQoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItPC0gRG9uZSBmaXJpbmcgbW9kdWxlIGZpbmlzaGVkIGV2ZW50IC08LSIpOwoJfQoJCgkvKioKCSAqIEZpcmUgYSBwdWJsaXNoIHN0b3AgZXZlbnQuCgkgKgoJICogQHBhcmFtIHN0YXR1cyBwdWJsaXNoaW5nIHN0YXR1cwoJICovCglwcml2YXRlIHZvaWQgZmlyZVB1Ymxpc2hGaW5pc2hlZChJU3RhdHVzIHN0YXR1cykgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0+LSBGaXJpbmcgcHVibGlzaGluZyBmaW5pc2hlZCBldmVudDogIiArIHN0YXR1cyArICIgLT4tIik7CgkKCQlpZiAocHVibGlzaExpc3RlbmVycyA9PSBudWxsIHx8IHB1Ymxpc2hMaXN0ZW5lcnMuaXNFbXB0eSgpKQoJCQlyZXR1cm47CgoJCWludCBzaXplID0gcHVibGlzaExpc3RlbmVycy5zaXplKCk7CgkJSVB1Ymxpc2hMaXN0ZW5lcltdIHNybCA9IG5ldyBJUHVibGlzaExpc3RlbmVyW3NpemVdOwoJCXB1Ymxpc2hMaXN0ZW5lcnMudG9BcnJheShzcmwpOwoKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICIgIEZpcmluZyBwdWJsaXNoaW5nIGZpbmlzaGVkIGV2ZW50IHRvICIgKyBzcmxbaV0pOwoJCQl0cnkgewoJCQkJc3JsW2ldLnB1Ymxpc2hGaW5pc2hlZCh0aGlzLCBzdGF0dXMpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgcHVibGlzaGluZyBmaW5pc2hlZCBldmVudCB0byAiICsgc3JsW2ldLCBlKTsKCQkJfQoJCX0KCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLTwtIERvbmUgZmlyaW5nIHB1Ymxpc2hpbmcgZmluaXNoZWQgZXZlbnQgLTwtIik7Cgl9CgoJLyoqCgkgKiBGaXJlIGEgcHVibGlzaCBzdGF0ZSBjaGFuZ2UgZXZlbnQuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpcmVQdWJsaXNoU3RhdGVDaGFuZ2UoSU1vZHVsZVtdIG1vZHVsZSkgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0+LSBGaXJpbmcgcHVibGlzaCBzdGF0ZSBjaGFuZ2UgZXZlbnQ6ICIgKyBtb2R1bGUgKyAiIC0+LSIpOwoJCgkJaWYgKG5vdGlmaWNhdGlvbk1hbmFnZXIgPT0gbnVsbCB8fCBub3RpZmljYXRpb25NYW5hZ2VyLmhhc0xpc3RlbmVyRW50cmllcygpKQoJCQlyZXR1cm47CgkKCQlub3RpZmljYXRpb25NYW5hZ2VyLmJyb2FkY2FzdENoYW5nZSgKCQkJbmV3IFNlcnZlckV2ZW50KFNlcnZlckV2ZW50Lk1PRFVMRV9DSEFOR0UgfCBTZXJ2ZXJFdmVudC5QVUJMSVNIX1NUQVRFX0NIQU5HRSwgdGhpcywgbW9kdWxlLCBnZXRNb2R1bGVTdGF0ZShtb2R1bGUpLCAKCQkJCWdldE1vZHVsZVB1Ymxpc2hTdGF0ZShtb2R1bGUpLCBnZXRNb2R1bGVSZXN0YXJ0U3RhdGUobW9kdWxlKSkpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIHRoZSBzZXJ2ZXIgaXMgaW4gYSBzdGF0ZSB0aGF0IGl0IGNhbgoJICogYmUgcHVibGlzaGVkIHRvLgoJICoKCSAqIEByZXR1cm4gYm9vbGVhbgoJICovCglwdWJsaWMgSVN0YXR1cyBjYW5QdWJsaXNoKCkgewoJCS8vIGNhbid0IHB1Ymxpc2ggaWYgdGhlIHNlcnZlciBpcyBzdGFydGluZyBvciBzdG9wcGluZwoJCWludCBzdGF0ZSA9IGdldFNlcnZlclN0YXRlKCk7CgkJaWYgKHN0YXRlID09IFNUQVRFX1NUQVJUSU5HIHx8IHN0YXRlID09IFNUQVRFX1NUT1BQSU5HKQoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5lcnJvclB1Ymxpc2hTdGFydGluZywgbnVsbCk7CgkKCQkvLyBjYW4ndCBwdWJsaXNoIGlmIHRoZXJlIGlzIG5vIGNvbmZpZ3VyYXRpb24KCQlpZiAoZ2V0U2VydmVyVHlwZSgpID09IG51bGwgfHwgZ2V0U2VydmVyVHlwZSgpLmhhc1NlcnZlckNvbmZpZ3VyYXRpb24oKSAmJiBjb25maWd1cmF0aW9uID09IG51bGwpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yUHVibGlzaE5vQ29uZmlndXJhdGlvbiwgbnVsbCk7CgkKCQkvLyByZXR1cm4gdHJ1ZSBpZiB0aGUgY29uZmlndXJhdGlvbiBjYW4gYmUgcHVibGlzaGVkCgkJaWYgKGdldFNlcnZlclB1Ymxpc2hTdGF0ZSgpICE9IFBVQkxJU0hfU1RBVEVfTk9ORSkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMuY2FuUHVibGlzaE9rLCBudWxsKTsKCgkJLy8gcmV0dXJuIHRydWUgaWYgYW55IG1vZHVsZXMgY2FuIGJlIHB1Ymxpc2hlZAoJCWNsYXNzIFRlbXAgewoJCQlib29sZWFuIGZvdW5kID0gZmFsc2U7CgkJfQoJCS8vZmluYWwgVGVtcCB0ZW1wID0gbmV3IFRlbXAoKTsKCQkKCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5jYW5QdWJsaXNoT2ssIG51bGwpOwoJCgkJLypJTW9kdWxlVmlzaXRvciB2aXNpdG9yID0gbmV3IElNb2R1bGVWaXNpdG9yKCkgewoJCQlwdWJsaWMgYm9vbGVhbiB2aXNpdChJTW9kdWxlW10gcGFyZW50cywgSU1vZHVsZSBtb2R1bGUpIHsKCQkJCWlmIChnZXRNb2R1bGVQdWJsaXNoU3RhdGUobW9kdWxlKSAhPSBQVUJMSVNIX1NUQVRFX05PTkUpIHsKCQkJCQl0ZW1wLmZvdW5kID0gdHJ1ZTsKCQkJCQlyZXR1cm4gZmFsc2U7CgkJCQl9CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX07CgkJU2VydmVyVXRpbC52aXNpdCh0aGlzLCB2aXNpdG9yLCBudWxsKTsKCQkKCQlyZXR1cm4gdGVtcC5mb3VuZDsqLwoJfQoKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIHRoZSBzZXJ2ZXIgaXMgaW4gYSBzdGF0ZSB0aGF0IGl0IGNhbgoJICogYmUgcHVibGlzaGVkIHRvLgoJICoKCSAqIEByZXR1cm4gYm9vbGVhbgoJICovCglwdWJsaWMgYm9vbGVhbiBzaG91bGRQdWJsaXNoKCkgewoJCWlmICghY2FuUHVibGlzaCgpLmlzT0soKSkKCQkJcmV0dXJuIGZhbHNlOwoJCgkJaWYgKGdldFNlcnZlclB1Ymxpc2hTdGF0ZSgpICE9IFBVQkxJU0hfU1RBVEVfTk9ORSkKCQkJcmV0dXJuIHRydWU7CgkKCQkvL2lmIChnZXRVbnB1Ymxpc2hlZE1vZHVsZXMoKS5sZW5ndGggPiAwKQoJCXJldHVybiB0cnVlOwoJCgkJLy9yZXR1cm4gZmFsc2U7Cgl9CgoJcHJvdGVjdGVkIFNlcnZlclB1Ymxpc2hJbmZvIGdldFNlcnZlclB1Ymxpc2hJbmZvKCkgewoJCWlmIChwdWJsaXNoSW5mbyA9PSBudWxsKSB7CgkJCXB1Ymxpc2hJbmZvID0gUHVibGlzaEluZm8uZ2V0SW5zdGFuY2UoKS5nZXRTZXJ2ZXJQdWJsaXNoSW5mbyh0aGlzKTsKCQl9CgkJcmV0dXJuIHB1Ymxpc2hJbmZvOwoJfQoKCS8qCgkgKiBQdWJsaXNoIHRvIHRoZSBzZXJ2ZXIgdXNpbmcgdGhlIHByb2dyZXNzIG1vbml0b3IuIFRoZSByZXN1bHQgb2YgdGhlCgkgKiBwdWJsaXNoIG9wZXJhdGlvbiBpcyByZXR1cm5lZCBhcyBhbiBJU3RhdHVzLgoJICovCglwdWJsaWMgSVN0YXR1cyBwdWJsaXNoKGZpbmFsIGludCBraW5kLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlpZiAoZ2V0U2VydmVyVHlwZSgpID09IG51bGwpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yUHVibGlzaGluZywgbnVsbCk7CgoJCS8vIGNoZWNrIHdoYXQgaXMgb3V0IG9mIHN5bmMgYW5kIHB1Ymxpc2gKCQlpZiAoZ2V0U2VydmVyVHlwZSgpLmhhc1NlcnZlckNvbmZpZ3VyYXRpb24oKSAmJiBjb25maWd1cmF0aW9uID09IG51bGwpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yTm9Db25maWd1cmF0aW9uLCBudWxsKTsKCQkKCQlyZXR1cm4gZG9QdWJsaXNoKGtpbmQsIG1vbml0b3IpOwoJfQoKCXByb3RlY3RlZCBJU3RhdHVzIGRvUHVibGlzaChpbnQga2luZCwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLS0+LS0gUHVibGlzaGluZyB0byBzZXJ2ZXI6ICIgKyB0b1N0cmluZygpICsgIiAtLT4tLSIpOwoKCQlmaW5hbCBMaXN0IG1vZHVsZUxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJZmluYWwgTGlzdCBraW5kTGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCQkKCQlmaW5hbCBTZXJ2ZXJQdWJsaXNoSW5mbyBzcGkgPSBnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpOwoJCQoJCUlNb2R1bGVWaXNpdG9yIHZpc2l0b3IgPSBuZXcgSU1vZHVsZVZpc2l0b3IoKSB7CgkJCXB1YmxpYyBib29sZWFuIHZpc2l0KElNb2R1bGVbXSBtb2R1bGUpIHsKCQkJCW1vZHVsZUxpc3QuYWRkKG1vZHVsZSk7CgkJCQkKCQkJCWlmIChzcGkuaGFzTW9kdWxlUHVibGlzaEluZm8obW9kdWxlKSkgewoJCQkJCWlmIChnZXRQdWJsaXNoZWRSZXNvdXJjZURlbHRhKG1vZHVsZSkubGVuZ3RoID09IDApCgkJCQkJCWtpbmRMaXN0LmFkZChuZXcgSW50ZWdlcihTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZS5OT19DSEFOR0UpKTsKCQkJCQllbHNlCgkJCQkJCWtpbmRMaXN0LmFkZChuZXcgSW50ZWdlcihTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZS5DSEFOR0VEKSk7CgkJCQl9IGVsc2UKCQkJCQlraW5kTGlzdC5hZGQobmV3IEludGVnZXIoU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUuQURERUQpKTsKCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJfTsKCgkJdmlzaXQodmlzaXRvciwgbW9uaXRvcik7CgkJCgkJTGlzdCB0YXNrcyA9IGdldFRhc2tzKG1vZHVsZUxpc3QpOwoJCQoJCXNwaS5hZGRSZW1vdmVkTW9kdWxlcyhtb2R1bGVMaXN0LCBraW5kTGlzdCk7CgkJCgkJd2hpbGUgKG1vZHVsZUxpc3Quc2l6ZSgpID4ga2luZExpc3Quc2l6ZSgpKSB7CgkJCWtpbmRMaXN0LmFkZChuZXcgSW50ZWdlcihTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZS5SRU1PVkVEKSk7CgkJfQoKCQlpbnQgc2l6ZSA9IDIwMDAgKyAzNTAwICogbW9kdWxlTGlzdC5zaXplKCkgKyA1MDAgKiB0YXNrcy5zaXplKCk7CgkJCgkJbW9uaXRvciA9IFByb2dyZXNzVXRpbC5nZXRNb25pdG9yRm9yKG1vbml0b3IpOwoJCW1vbml0b3IuYmVnaW5UYXNrKE5MUy5iaW5kKE1lc3NhZ2VzLnB1Ymxpc2hpbmcsIHRvU3RyaW5nKCkpLCBzaXplKTsKCgkJLy8gVE9ETyAtIGdyb3VwIHVwIHN0YXR1cyB1bnRpbCB0aGUgZW5kIGFuZCB1c2UgYmV0dGVyIG1lc3NhZ2UgYmFzZWQgb24gc3VjY2VzcyBvciBmYWlsdXJlCgkJTXVsdGlTdGF0dXMgbXVsdGkgPSBuZXcgTXVsdGlTdGF0dXMoU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMucHVibGlzaGluZ1N0YXR1cywgbnVsbCk7CgoJCWlmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5JTkZPLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5wdWJsaXNoaW5nQ2FuY2VsbGVkLCBudWxsKTsKCQkKCQkvLyBzdGFydCBwdWJsaXNoaW5nCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiQ2FsbGluZyBwdWJsaXNoU3RhcnQoKSIpOwoJCWZpcmVQdWJsaXNoU3RhcnRlZCgpOwoJCXRyeSB7CgkJCWdldEJlaGF2aW91ckRlbGVnYXRlKCkucHVibGlzaFN0YXJ0KFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDEwMDApKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLklORk8sICJDb3JlRXhjZXB0aW9uIHB1Ymxpc2hpbmcgdG8gIiArIHRvU3RyaW5nKCksIGNlKTsKCQkJZmlyZVB1Ymxpc2hGaW5pc2hlZChjZS5nZXRTdGF0dXMoKSk7CgkJCXJldHVybiBjZS5nZXRTdGF0dXMoKTsKCQl9CgkJCgkJLy8gcGVyZm9ybSB0YXNrcwoJCUlTdGF0dXMgdGFza1N0YXR1cyA9IHBlcmZvcm1UYXNrcyh0YXNrcywgbW9uaXRvcik7CgkJaWYgKHRhc2tTdGF0dXMgIT0gbnVsbCkKCQkJbXVsdGkuYWRkKHRhc2tTdGF0dXMpOwoJCQoJCS8vIHB1Ymxpc2ggdGhlIHNlcnZlcgoJCXRyeSB7CgkJCWlmICghbW9uaXRvci5pc0NhbmNlbGVkKCkgJiYgc2VydmVyVHlwZS5oYXNTZXJ2ZXJDb25maWd1cmF0aW9uKCkpIHsKCQkJCWdldEJlaGF2aW91ckRlbGVnYXRlKCkucHVibGlzaFNlcnZlcihraW5kLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAxMDAwKSk7CgkJCX0KCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLklORk8sICJDb3JlRXhjZXB0aW9uIHB1Ymxpc2hpbmcgdG8gIiArIHRvU3RyaW5nKCksIGNlKTsKCQkJbXVsdGkuYWRkKGNlLmdldFN0YXR1cygpKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBwdWJsaXNoaW5nIGNvbmZpZ3VyYXRpb24gdG8gIiArIHRvU3RyaW5nKCksIGUpOwoJCQltdWx0aS5hZGQobmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5lcnJvclB1Ymxpc2hpbmcsIGUpKTsKCQl9CgkJCgkJLy8gcHVibGlzaCBtb2R1bGVzCgkJaWYgKCFtb25pdG9yLmlzQ2FuY2VsZWQoKSkgewoJCQl0cnkgewoJCQkJcHVibGlzaE1vZHVsZXMoa2luZCwgbW9kdWxlTGlzdCwga2luZExpc3QsIG11bHRpLCBtb25pdG9yKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLldBUk5JTkcsICJFcnJvciB3aGlsZSBwdWJsaXNoaW5nIG1vZHVsZXMiLCBlKTsKCQkJCW11bHRpLmFkZChuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yUHVibGlzaGluZywgZSkpOwoJCQl9CgkJfQoJCQoJCS8vIGVuZCB0aGUgcHVibGlzaGluZwoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkNhbGxpbmcgcHVibGlzaEZpbmlzaCgpIik7CgkJdHJ5IHsKCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKS5wdWJsaXNoRmluaXNoKFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDUwMCkpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuSU5GTywgIkNvcmVFeGNlcHRpb24gcHVibGlzaGluZyB0byAiICsgdG9TdHJpbmcoKSwgY2UpOwoJCQltdWx0aS5hZGQoY2UuZ2V0U3RhdHVzKCkpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHN0b3BwaW5nIHB1Ymxpc2ggdG8gIiArIHRvU3RyaW5nKCksIGUpOwoJCQltdWx0aS5hZGQobmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5lcnJvclB1Ymxpc2hpbmcsIGUpKTsKCQl9CgkJCgkJaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKSB7CgkJCUlTdGF0dXMgc3RhdHVzID0gbmV3IFN0YXR1cyhJU3RhdHVzLklORk8sIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLnB1Ymxpc2hpbmdDYW5jZWxsZWQsIG51bGwpOwoJCQltdWx0aS5hZGQoc3RhdHVzKTsKCQl9CgoJCU11bHRpU3RhdHVzIHBzID0gbmV3IE11bHRpU3RhdHVzKFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLnB1Ymxpc2hpbmdTdG9wLCBudWxsKTsKCQlwcy5hZGQobXVsdGkpOwoJCWZpcmVQdWJsaXNoRmluaXNoZWQobXVsdGkpOwoJCQoJCXNwaS5zYXZlKCk7CgoJCW1vbml0b3IuZG9uZSgpOwoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItLTwtLSBEb25lIHB1Ymxpc2hpbmcgLS08LS0iKTsKCQkKCQlpZiAobXVsdGkuZ2V0Q2hpbGRyZW4oKS5sZW5ndGggPT0gMSkKCQkJcmV0dXJuIG11bHRpLmdldENoaWxkcmVuKClbMF07CgkJCgkJcmV0dXJuIG11bHRpOwoJfQoKCS8qKgoJICogUHVibGlzaCBhIHNpbmdsZSBtb2R1bGUuCgkgKi8KCXByb3RlY3RlZCBJU3RhdHVzIHB1Ymxpc2hNb2R1bGUoaW50IGtpbmQsIElNb2R1bGVbXSBtb2R1bGUsIGludCBkZWx0YUtpbmQsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlB1Ymxpc2hpbmcgbW9kdWxlOiAiICsgbW9kdWxlKTsKCQkKCQlpbnQgc2l6ZSA9IG1vZHVsZS5sZW5ndGg7CgkJSU1vZHVsZSBtID0gbW9kdWxlW3NpemUgLSAxXTsKCQltb25pdG9yLmJlZ2luVGFzayhOTFMuYmluZChNZXNzYWdlcy5wdWJsaXNoaW5nTW9kdWxlLCBtLmdldE5hbWUoKSksIDEwMDApOwoJCQoJCWZpcmVNb2R1bGVQdWJsaXNoU3RhcnRlZChtb2R1bGUpOwoJCQoJCUlTdGF0dXMgc3RhdHVzID0gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBOTFMuYmluZChNZXNzYWdlcy5wdWJsaXNoZWRNb2R1bGUsIG0uZ2V0TmFtZSgpKSwgbnVsbCk7CgkJdHJ5IHsKCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKS5wdWJsaXNoTW9kdWxlKGtpbmQsIGRlbHRhS2luZCwgbW9kdWxlLCBtb25pdG9yKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCXN0YXR1cyA9IGNlLmdldFN0YXR1cygpOwoJCX0KCQlmaXJlTW9kdWxlUHVibGlzaEZpbmlzaGVkKG1vZHVsZSwgc3RhdHVzKTsKCQkKCQkvKlRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkRlbHRhOiIpOwoJCUlNb2R1bGVSZXNvdXJjZURlbHRhW10gZGVsdGEgPSBnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpLmdldERlbHRhKHBhcmVudHMsIG1vZHVsZSk7CgkJaW50IHNpemUgPSBkZWx0YS5sZW5ndGg7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJKChNb2R1bGVSZXNvdXJjZURlbHRhKWRlbHRhW2ldKS50cmFjZSgiPiAgIik7CgkJfSovCgkJaWYgKGRlbHRhS2luZCA9PSBTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZS5SRU1PVkVEKQoJCQlnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpLnJlbW92ZU1vZHVsZVB1Ymxpc2hJbmZvKG1vZHVsZSk7CgkJZWxzZQoJCQlnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpLmZpbGwobW9kdWxlKTsKCQkKCQltb25pdG9yLmRvbmUoKTsKCQkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJEb25lIHB1Ymxpc2hpbmc6ICIgKyBtb2R1bGUpOwoJCXJldHVybiBzdGF0dXM7Cgl9CgoJLyoqCgkgKiBQdWJsaXNoZXMgdGhlIGdpdmVuIG1vZHVsZXMuIFJldHVybnMgdHJ1ZSBpZiB0aGUgcHVibGlzaGluZwoJICogc2hvdWxkIGNvbnRpbnVlLCBvciBmYWxzZSBpZiBwdWJsaXNoaW5nIGhhcyBmYWlsZWQgb3IgaXMgY2FuY2VsbGVkLgoJICogCgkgKiBVc2VzIDUwMCB0aWNrcyBwbHVzIDM1MDAgdGlja3MgcGVyIG1vZHVsZQoJICovCglwcm90ZWN0ZWQgdm9pZCBwdWJsaXNoTW9kdWxlcyhpbnQga2luZCwgTGlzdCBtb2R1bGVzMiwgTGlzdCBkZWx0YUtpbmQsIE11bHRpU3RhdHVzIG11bHRpLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlpZiAobW9kdWxlczIgPT0gbnVsbCkKCQkJcmV0dXJuOwoKCQlpbnQgc2l6ZSA9IG1vZHVsZXMyLnNpemUoKTsKCQlpZiAoc2l6ZSA9PSAwKQoJCQlyZXR1cm47CgkJCgkJaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKQoJCQlyZXR1cm47CgoJCS8vIHB1Ymxpc2ggbW9kdWxlcwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCUlTdGF0dXMgc3RhdHVzID0gcHVibGlzaE1vZHVsZShraW5kLCAoSU1vZHVsZVtdKSBtb2R1bGVzMi5nZXQoaSksICgoSW50ZWdlcilkZWx0YUtpbmQuZ2V0KGkpKS5pbnRWYWx1ZSgpLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAzMDAwKSk7CgkJCW11bHRpLmFkZChzdGF0dXMpOwoJCX0KCX0KCgkvKgoJICogUmV0dXJucyB0aGUgbW9kdWxlIHJlc291cmNlcyB0aGF0IGhhdmUgYmVlbiBwdWJsaXNoZWQuCgkgKiAKCSAqIEBzZWUgU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUuZ2V0UHVibGlzaGVkUmVzb3VyY2VzKElNb2R1bGVbXSwgSU1vZHVsZSkKCSAqLwoJcHVibGljIElNb2R1bGVSZXNvdXJjZVtdIGdldFB1Ymxpc2hlZFJlc291cmNlcyhJTW9kdWxlW10gbW9kdWxlKSB7CgkJcmV0dXJuIGdldFNlcnZlclB1Ymxpc2hJbmZvKCkuZ2V0TW9kdWxlUHVibGlzaEluZm8obW9kdWxlKS5nZXRSZXNvdXJjZXMoKTsKCX0KCgkvKgoJICogUmV0dXJucyB0aGUgZGVsdGEgb2YgdGhlIGN1cnJlbnQgbW9kdWxlIHJlc291cmNlcyB0aGF0IGhhdmUgYmVlbgoJICogcHVibGlzaGVkIGNvbXBhcmVkIHRvIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBtb2R1bGUuCgkgKiAKCSAqIEBzZWUgU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUuZ2V0UHVibGlzaGVkUmVzb3VyY2VEZWx0YShJTW9kdWxlW10sIElNb2R1bGUpCgkgKi8KCXB1YmxpYyBJTW9kdWxlUmVzb3VyY2VEZWx0YVtdIGdldFB1Ymxpc2hlZFJlc291cmNlRGVsdGEoSU1vZHVsZVtdIG1vZHVsZSkgewoJCXJldHVybiBnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpLmdldERlbHRhKG1vZHVsZSk7Cgl9CgoJcHJvdGVjdGVkIExpc3QgZ2V0VGFza3MoTGlzdCBtb2R1bGVzMikgewoJCUxpc3QgdGFza3MgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCgkJU3RyaW5nIHNlcnZlclR5cGVJZCA9IGdldFNlcnZlclR5cGUoKS5nZXRJZCgpOwoJCQoJCUlQdWJsaXNoVGFza1tdIHB1Ymxpc2hUYXNrcyA9IFNlcnZlclBsdWdpbi5nZXRQdWJsaXNoVGFza3MoKTsKCQlpZiAocHVibGlzaFRhc2tzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBwdWJsaXNoVGFza3MubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJSVB1Ymxpc2hUYXNrIHRhc2sgPSBwdWJsaXNoVGFza3NbaV07CgkJCQlpZiAodGFzay5zdXBwb3J0c1R5cGUoc2VydmVyVHlwZUlkKSkgewoJCQkJCUlPcHRpb25hbFRhc2tbXSB0YXNrczIgPSB0YXNrLmdldFRhc2tzKHRoaXMsIG1vZHVsZXMyKTsKCQkJCQlpZiAodGFza3MyICE9IG51bGwpIHsKCQkJCQkJaW50IHNpemUyID0gdGFza3MyLmxlbmd0aDsKCQkJCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKSB7CgkJCQkJCQlpZiAodGFza3MyW2pdLmdldFN0YXR1cygpID09IElPcHRpb25hbFRhc2suVEFTS19NQU5EQVRPUlkpCgkJCQkJCQkJdGFza3MuYWRkKHRhc2tzMltqXSk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgoJCWludCBzaXplID0gdGFza3Muc2l6ZSgpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZSAtIDE7IGkrKykgewoJCQlmb3IgKGludCBqID0gaSArIDE7IGogPCBzaXplOyBqKyspIHsKCQkJCUlPcmRlcmVkIGEgPSAoSU9yZGVyZWQpIHRhc2tzLmdldChpKTsKCQkJCUlPcmRlcmVkIGIgPSAoSU9yZGVyZWQpIHRhc2tzLmdldChqKTsKCQkJCWlmIChhLmdldE9yZGVyKCkgPiBiLmdldE9yZGVyKCkpIHsKCQkJCQlPYmplY3QgdGVtcCA9IGE7CgkJCQkJdGFza3Muc2V0KGksIGIpOwoJCQkJCXRhc2tzLnNldChqLCB0ZW1wKTsKCQkJCX0KCQkJfQoJCX0KCQkKCQlyZXR1cm4gdGFza3M7Cgl9CgoJcHJvdGVjdGVkIElTdGF0dXMgcGVyZm9ybVRhc2tzKExpc3QgdGFza3MsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlBlcmZvcm1pbmcgdGFza3M6ICIgKyB0YXNrcy5zaXplKCkpOwoJCQoJCWlmICh0YXNrcy5pc0VtcHR5KCkpCgkJCXJldHVybiBudWxsOwoJCQoJCVN0YXR1cyBtdWx0aSA9IG5ldyBNdWx0aVN0YXR1cyhTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy50YXNrUGVyZm9ybWluZywgbnVsbCk7CgoJCUl0ZXJhdG9yIGl0ZXJhdG9yID0gdGFza3MuaXRlcmF0b3IoKTsKCQl3aGlsZSAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCUlPcHRpb25hbFRhc2sgdGFzayA9IChJT3B0aW9uYWxUYXNrKSBpdGVyYXRvci5uZXh0KCk7CgkJCW1vbml0b3Iuc3ViVGFzayhOTFMuYmluZChNZXNzYWdlcy50YXNrUGVyZm9ybWluZywgdGFzay50b1N0cmluZygpKSk7CgkJCXRyeSB7CgkJCQl0YXNrLmV4ZWN1dGUoUHJvZ3Jlc3NVdGlsLmdldFN1Yk1vbml0b3JGb3IobW9uaXRvciwgNTAwKSk7CgkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIlRhc2sgZmFpbGVkIiwgY2UpOwoJCQl9CgkJCWlmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkJCXJldHVybiBtdWx0aTsKCQl9CgkJCgkJLy8gc2F2ZSBzZXJ2ZXIgYW5kIGNvbmZpZ3VyYXRpb24KCQkvKnRyeSB7CgkJCVNlcnZlclV0aWwuc2F2ZShzZXJ2ZXIsIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDEwMDApKTsKCQkJU2VydmVyVXRpbC5zYXZlKGNvbmZpZ3VyYXRpb24sIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDEwMDApKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIHNlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHNhdmluZyBzZXJ2ZXIgYW5kL29yIGNvbmZpZ3VyYXRpb24iLCBzZSk7CgkJCW11bHRpLmFkZENoaWxkKHNlLmdldFN0YXR1cygpKTsKCQl9Ki8KCgkJcmV0dXJuIG11bHRpOwoJfQoJCgkvKiAobm9uLUphdmFkb2MpCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5JQWRhcHRhYmxlI2dldEFkYXB0ZXIoamF2YS5sYW5nLkNsYXNzKQoJICovCglwdWJsaWMgT2JqZWN0IGdldEFkYXB0ZXIoQ2xhc3MgYWRhcHRlcikgewoJCVNlcnZlckRlbGVnYXRlIGRlbGVnYXRlMiA9IGdldERlbGVnYXRlKCk7CgkJaWYgKGFkYXB0ZXIuaXNJbnN0YW5jZShkZWxlZ2F0ZTIpKQoJCQlyZXR1cm4gZGVsZWdhdGUyOwoJCVNlcnZlckJlaGF2aW91ckRlbGVnYXRlIGRlbGVnYXRlMyA9IGdldEJlaGF2aW91ckRlbGVnYXRlKCk7CgkJaWYgKGFkYXB0ZXIuaXNJbnN0YW5jZShkZWxlZ2F0ZTMpKQoJCQlyZXR1cm4gZGVsZWdhdGUzOwoJCXJldHVybiBQbGF0Zm9ybS5nZXRBZGFwdGVyTWFuYWdlcigpLmdldEFkYXB0ZXIodGhpcywgYWRhcHRlcik7Cgl9CgoJcHVibGljIFN0cmluZyB0b1N0cmluZygpIHsKCQlyZXR1cm4gZ2V0TmFtZSgpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIHRoZSBzZXJ2ZXIgaXMgaW4gYSBzdGF0ZSB0aGF0IGl0IGNhbgoJICogYmUgc3RhcnRlZCwgYW5kIHN1cHBvcnRzIHRoZSBnaXZlbiBtb2RlLgoJICoKCSAqIEBwYXJhbSBtb2RlMgoJICogQHJldHVybiBzdGF0dXMKCSAqLwoJcHVibGljIElTdGF0dXMgY2FuU3RhcnQoU3RyaW5nIG1vZGUyKSB7CgkJaW50IHN0YXRlID0gZ2V0U2VydmVyU3RhdGUoKTsKCQlpZiAoc3RhdGUgIT0gU1RBVEVfU1RPUFBFRCAmJiBzdGF0ZSAhPSBTVEFURV9VTktOT1dOKQoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5jYW5TdGFydEVycm9yU3RhdGUsIG51bGwpOwoJCQoJCWlmIChnZXRTZXJ2ZXJUeXBlKCkgPT0gbnVsbCB8fCAhZ2V0U2VydmVyVHlwZSgpLnN1cHBvcnRzTGF1bmNoTW9kZShtb2RlMikpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yTGF1bmNoTW9kZSwgbnVsbCk7CgoJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmNhblN0YXJ0T2ssIG51bGwpOwoJfQoJCglwdWJsaWMgSUxhdW5jaCBnZXRFeGlzdGluZ0xhdW5jaCgpIHsKCQlJTGF1bmNoTWFuYWdlciBsYXVuY2hNYW5hZ2VyID0gRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldExhdW5jaE1hbmFnZXIoKTsKCQkKCQlJTGF1bmNoW10gbGF1bmNoZXMgPSBsYXVuY2hNYW5hZ2VyLmdldExhdW5jaGVzKCk7CgkJaW50IHNpemUgPSBsYXVuY2hlcy5sZW5ndGg7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJSUxhdW5jaENvbmZpZ3VyYXRpb24gbGF1bmNoQ29uZmlnID0gbGF1bmNoZXNbaV0uZ2V0TGF1bmNoQ29uZmlndXJhdGlvbigpOwoJCQl0cnkgewoJCQkJaWYgKGxhdW5jaENvbmZpZyAhPSBudWxsKSB7CgkJCQkJU3RyaW5nIHNlcnZlcklkID0gbGF1bmNoQ29uZmlnLmdldEF0dHJpYnV0ZShTRVJWRVJfSUQsIChTdHJpbmcpIG51bGwpOwoJCQkJCWlmIChnZXRJZCgpLmVxdWFscyhzZXJ2ZXJJZCkpIHsKCQkJCQkJaWYgKCFsYXVuY2hlc1tpXS5pc1Rlcm1pbmF0ZWQoKSkKCQkJCQkJCXJldHVybiBsYXVuY2hlc1tpXTsKCQkJCQl9CgkJCQl9CgkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkJLy8gaWdub3JlCgkJCX0KCQl9CgkJCgkJcmV0dXJuIG51bGw7Cgl9CgoJcHVibGljIHZvaWQgc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKElMYXVuY2hDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgd29ya2luZ0NvcHksIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXRyeSB7CgkJCWdldEJlaGF2aW91ckRlbGVnYXRlKCkuc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKHdvcmtpbmdDb3B5LCBtb25pdG9yKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIHNldExhdW5jaERlZmF1bHRzKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCX0KCX0KCglwdWJsaWMgdm9pZCBpbXBvcnRDb25maWd1cmF0aW9uKElSdW50aW1lIHJ1bnRpbWUyLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQl0cnkgewoJCQlnZXREZWxlZ2F0ZSgpLmltcG9ydENvbmZpZ3VyYXRpb24ocnVudGltZTIsIG1vbml0b3IpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgc2V0TGF1bmNoRGVmYXVsdHMoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJfQoJfQoKCS8qKgoJICogUmV0dXJuIHRoZSBsYXVuY2ggY29uZmlndXJhdGlvbiBmb3IgdGhpcyBzZXJ2ZXIuIElmIG9uZSBkb2VzIG5vdCBleGlzdCwgaXQKCSAqIHdpbGwgYmUgY3JlYXRlZCBpZiAiY3JlYXRlIiBpcyB0cnVlLCBhbmQgb3RoZXJ3aXNlIHdpbGwgcmV0dXJuIG51bGwuCgkgKiAKCSAqIEBwYXJhbSBjcmVhdGUgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSBuZXcgbGF1bmNoIGNvbmZpZ3VyYXRpb24gc2hvdWxkIGJlCgkgKiAgICBjcmVhdGVkIGlmIHRoZXJlIGFyZSBub25lIGFscmVhZHkKCSAqIEBwYXJhbSBtb25pdG9yIGEgcHJvZ3Jlc3MgbW9uaXRvciwgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgcHJvZ3Jlc3MKCSAqICAgIHJlcG9ydGluZyBhbmQgY2FuY2VsbGF0aW9uIGFyZSBub3QgZGVzaXJlZAoJICogQHJldHVybiB0aGUgbGF1bmNoIGNvbmZpZ3VyYXRpb24sIG5vIDxjb2RlPm51bGw8L2NvZGU+IGlmIHRoZXJlIHdhcyBubwoJICogICAgZXhpc3RpbmcgbGF1bmNoIGNvbmZpZ3VyYXRpb24gYW5kIDxjb2RlPmNyZWF0ZTwvY29kZT4gd2FzIGZhbHNlCgkgKiBAdGhyb3dzIENvcmVFeGNlcHRpb24KCSAqLwoJcHVibGljIElMYXVuY2hDb25maWd1cmF0aW9uIGdldExhdW5jaENvbmZpZ3VyYXRpb24oYm9vbGVhbiBjcmVhdGUsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUlMYXVuY2hDb25maWd1cmF0aW9uVHlwZSBsYXVuY2hDb25maWdUeXBlID0gKChTZXJ2ZXJUeXBlKSBnZXRTZXJ2ZXJUeXBlKCkpLmdldExhdW5jaENvbmZpZ3VyYXRpb25UeXBlKCk7CgkJCgkJSUxhdW5jaE1hbmFnZXIgbGF1bmNoTWFuYWdlciA9IERlYnVnUGx1Z2luLmdldERlZmF1bHQoKS5nZXRMYXVuY2hNYW5hZ2VyKCk7CgkJSUxhdW5jaENvbmZpZ3VyYXRpb25bXSBsYXVuY2hDb25maWdzID0gbnVsbDsKCQl0cnkgewoJCQlsYXVuY2hDb25maWdzID0gbGF1bmNoTWFuYWdlci5nZXRMYXVuY2hDb25maWd1cmF0aW9ucyhsYXVuY2hDb25maWdUeXBlKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCQoJCWlmIChsYXVuY2hDb25maWdzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBsYXVuY2hDb25maWdzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCXRyeSB7CgkJCQkJU3RyaW5nIHNlcnZlcklkID0gbGF1bmNoQ29uZmlnc1tpXS5nZXRBdHRyaWJ1dGUoU0VSVkVSX0lELCAoU3RyaW5nKSBudWxsKTsKCQkJCQlpZiAoZ2V0SWQoKS5lcXVhbHMoc2VydmVySWQpKSB7CgkJCQkJCUlMYXVuY2hDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgd2MgPSBsYXVuY2hDb25maWdzW2ldLmdldFdvcmtpbmdDb3B5KCk7CgkJCQkJCXNldHVwTGF1bmNoQ29uZmlndXJhdGlvbih3YywgbW9uaXRvcik7CgkJCQkJCWlmICh3Yy5pc0RpcnR5KCkpCgkJCQkJCQlyZXR1cm4gd2MuZG9TYXZlKCk7CgkJCQkJCXJldHVybiBsYXVuY2hDb25maWdzW2ldOwoJCQkJCX0KCQkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNvbmZpZ3VyaW5nIGxhdW5jaCIsIGUpOwoJCQkJfQoJCQl9CgkJfQoJCQoJCWlmICghY3JlYXRlKQoJCQlyZXR1cm4gbnVsbDsKCQkKCQkvLyBjcmVhdGUgYSBuZXcgbGF1bmNoIGNvbmZpZ3VyYXRpb24KCQlTdHJpbmcgbGF1bmNoTmFtZSA9IGdldFZhbGlkTGF1bmNoQ29uZmlndXJhdGlvbk5hbWUoZ2V0TmFtZSgpKTsKCQlsYXVuY2hOYW1lID0gbGF1bmNoTWFuYWdlci5nZW5lcmF0ZVVuaXF1ZUxhdW5jaENvbmZpZ3VyYXRpb25OYW1lRnJvbShsYXVuY2hOYW1lKTsgCgkJSUxhdW5jaENvbmZpZ3VyYXRpb25Xb3JraW5nQ29weSB3YyA9IGxhdW5jaENvbmZpZ1R5cGUubmV3SW5zdGFuY2UobnVsbCwgbGF1bmNoTmFtZSk7CgkJd2Muc2V0QXR0cmlidXRlKFNFUlZFUl9JRCwgZ2V0SWQoKSk7CgkJc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKHdjLCBtb25pdG9yKTsKCQlyZXR1cm4gd2MuZG9TYXZlKCk7Cgl9CgoJcHJvdGVjdGVkIFN0cmluZyBnZXRWYWxpZExhdW5jaENvbmZpZ3VyYXRpb25OYW1lKFN0cmluZyBzKSB7CgkJaWYgKHMgPT0gbnVsbCB8fCBzLmxlbmd0aCgpID09IDApCgkJCXJldHVybiAiMSI7CgkJaW50IHNpemUgPSBJTlZBTElEX0NIQVJTLmxlbmd0aDsKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlzID0gcy5yZXBsYWNlKElOVkFMSURfQ0hBUlNbaV0sICdfJyk7CgkJfQoJCXJldHVybiBzOwoJfQoKCS8qKgoJICogQHNlZSBJU2VydmVyI3N0YXJ0KFN0cmluZywgSVByb2dyZXNzTW9uaXRvcikKCSAqLwoJcHVibGljIElMYXVuY2ggc3RhcnQoU3RyaW5nIG1vZGUyLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJTdGFydGluZyBzZXJ2ZXI6ICIgKyB0b1N0cmluZygpICsgIiwgbGF1bmNoTW9kZTogIiArIG1vZGUyKTsKCQoJCXRyeSB7CgkJCUlMYXVuY2hDb25maWd1cmF0aW9uIGxhdW5jaENvbmZpZyA9IGdldExhdW5jaENvbmZpZ3VyYXRpb24odHJ1ZSwgbW9uaXRvcik7CgkJCUlMYXVuY2ggbGF1bmNoID0gbGF1bmNoQ29uZmlnLmxhdW5jaChtb2RlMiwgbW9uaXRvcik7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkxhdW5jaDogIiArIGxhdW5jaCk7CgkJCXJldHVybiBsYXVuY2g7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHN0YXJ0aW5nIHNlcnZlciAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXRocm93IGU7CgkJfQoJfQoKCS8qKgoJICogQ2xlYW4gdXAgYW55IG9sZCBsYXVuY2ggY29uZmlndXJhdGlvbnMgd2l0aCB0aGUgY3VycmVudCBzZXJ2ZXIncyBpZC4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgZGVsZXRlTGF1bmNoQ29uZmlndXJhdGlvbnMoKSB7CgkJaWYgKGdldFNlcnZlclR5cGUoKSA9PSBudWxsKQoJCQlyZXR1cm47CgkJSUxhdW5jaE1hbmFnZXIgbGF1bmNoTWFuYWdlciA9IERlYnVnUGx1Z2luLmdldERlZmF1bHQoKS5nZXRMYXVuY2hNYW5hZ2VyKCk7CgkJSUxhdW5jaENvbmZpZ3VyYXRpb25UeXBlIGxhdW5jaENvbmZpZ1R5cGUgPSAoKFNlcnZlclR5cGUpIGdldFNlcnZlclR5cGUoKSkuZ2V0TGF1bmNoQ29uZmlndXJhdGlvblR5cGUoKTsKCQkKCQlJTGF1bmNoQ29uZmlndXJhdGlvbltdIGNvbmZpZ3MgPSBudWxsOwoJCXRyeSB7CgkJCWNvbmZpZ3MgPSBsYXVuY2hNYW5hZ2VyLmdldExhdW5jaENvbmZpZ3VyYXRpb25zKGxhdW5jaENvbmZpZ1R5cGUpOwoJCQlpbnQgc2l6ZSA9IGNvbmZpZ3MubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJdHJ5IHsKCQkJCQlpZiAoZ2V0SWQoKS5lcXVhbHMoY29uZmlnc1tpXS5nZXRBdHRyaWJ1dGUoU0VSVkVSX0lELCAoU3RyaW5nKSBudWxsKSkpCgkJCQkJCWNvbmZpZ3NbaV0uZGVsZXRlKCk7CgkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCS8vIGlnbm9yZQoJCQkJfQoJCQl9CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJfQoKCS8qKgoJICogQHNlZSBJU2VydmVyI2NhblJlc3RhcnQoU3RyaW5nKQoJICovCglwdWJsaWMgSVN0YXR1cyBjYW5SZXN0YXJ0KFN0cmluZyBtb2RlMikgewoJCWlmICghZ2V0U2VydmVyVHlwZSgpLnN1cHBvcnRzTGF1bmNoTW9kZShtb2RlMikpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yTGF1bmNoTW9kZSwgbnVsbCk7CgoJCWludCBzdGF0ZSA9IGdldFNlcnZlclN0YXRlKCk7CgkJaWYgKHN0YXRlID09IFNUQVRFX1NUQVJURUQpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmNhblJlc3RhcnRPaywgbnVsbCk7CgkJCgkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMuZXJyb3JSZXN0YXJ0Tm90U3RhcnRlZCwgbnVsbCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHJlc3RhcnQgc3RhdGUgb2YgdGhlIHNlcnZlci4gVGhpcwoJICogaW1wbGVtZW50YXRpb24gd2lsbCBhbHdheXMgcmV0dXJuIGZhbHNlIHdoZW4gdGhlIHNlcnZlcgoJICogaXMgc3RvcHBlZC4KCSAqCgkgKiBAcmV0dXJuIGJvb2xlYW4KCSAqLwoJcHVibGljIGJvb2xlYW4gZ2V0U2VydmVyUmVzdGFydFN0YXRlKCkgewoJCWlmIChnZXRTZXJ2ZXJTdGF0ZSgpID09IFNUQVRFX1NUT1BQRUQpCgkJCXJldHVybiBmYWxzZTsKCQlyZXR1cm4gc2VydmVyUmVzdGFydE5lZWRlZDsKCX0KCgkvKioKCSAqIFNldHMgdGhlIHNlcnZlciByZXN0YXJ0IHN0YXRlLgoJICoKCSAqIEBwYXJhbSBzdGF0ZSBib29sZWFuCgkgKi8KCXB1YmxpYyBzeW5jaHJvbml6ZWQgdm9pZCBzZXRTZXJ2ZXJSZXN0YXJ0U3RhdGUoYm9vbGVhbiBzdGF0ZSkgewoJCWlmIChzdGF0ZSA9PSBzZXJ2ZXJSZXN0YXJ0TmVlZGVkKQoJCQlyZXR1cm47CgkJc2VydmVyUmVzdGFydE5lZWRlZCA9IHN0YXRlOwoJCWZpcmVSZXN0YXJ0U3RhdGVDaGFuZ2VFdmVudCgpOwoJfQoKCS8qKgoJICogQHNlZSBJU2VydmVyI3Jlc3RhcnQoU3RyaW5nKQoJICovCglwdWJsaWMgdm9pZCByZXN0YXJ0KGZpbmFsIFN0cmluZyBtb2RlMikgewoJCWlmIChnZXRTZXJ2ZXJTdGF0ZSgpID09IFNUQVRFX1NUT1BQRUQpCgkJCXJldHVybjsKCQoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlJlc3RhcnRpbmcgc2VydmVyOiAiICsgZ2V0TmFtZSgpKTsKCQoJCXRyeSB7CgkJCXRyeSB7CgkJCQlnZXRCZWhhdmlvdXJEZWxlZ2F0ZSgpLnJlc3RhcnQobW9kZTIpOwoJCQkJcmV0dXJuOwoJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIHJlc3RhcnQoKSAiICsgdG9TdHJpbmcoKSk7CgkJCX0KCQkKCQkJLy8gYWRkIGxpc3RlbmVyIHRvIHN0YXJ0IGl0IGFzIHNvb24gYXMgaXQgaXMgc3RvcHBlZAoJCQlhZGRTZXJ2ZXJMaXN0ZW5lcihuZXcgSVNlcnZlckxpc3RlbmVyKCkgewoJCQkJcHVibGljIHZvaWQgc2VydmVyQ2hhbmdlZChTZXJ2ZXJFdmVudCBldmVudCkgewoJCQkJCWludCBldmVudEtpbmQgPSBldmVudC5nZXRLaW5kKCk7CgkJCQkJSVNlcnZlciBzZXJ2ZXIgPSBldmVudC5nZXRTZXJ2ZXIoKTsKCQkJCQlpZiAoZXZlbnRLaW5kID09IChTZXJ2ZXJFdmVudC5TRVJWRVJfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFKSkgewoJCQkJCQlpZiAoc2VydmVyLmdldFNlcnZlclN0YXRlKCkgPT0gU1RBVEVfU1RPUFBFRCkgewoJCQkJCQkJc2VydmVyLnJlbW92ZVNlcnZlckxpc3RlbmVyKHRoaXMpOwoKCQkJCQkJCS8vIHJlc3RhcnQgaW4gYSBxdWFydGVyIHNlY29uZCAoZ2l2ZSBvdGhlciBsaXN0ZW5lcnMgYSBjaGFuY2UKCQkJCQkJCS8vIHRvIGhlYXIgdGhlIHN0b3BwZWQgbWVzc2FnZSkKCQkJCQkJCVRocmVhZCB0ID0gbmV3IFRocmVhZCgpIHsKCQkJCQkJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQkJCQkJCXRyeSB7CgkJCQkJCQkJCQlUaHJlYWQuc2xlZXAoMjUwKTsKCQkJCQkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJCQkJCS8vIGlnbm9yZQoJCQkJCQkJCQl9CgkJCQkJCQkJCXRyeSB7CgkJCQkJCQkJCQlTZXJ2ZXIudGhpcy5zdGFydChtb2RlMiwgbmV3IE51bGxQcm9ncmVzc01vbml0b3IoKSk7CgkJCQkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciB3aGlsZSByZXN0YXJ0aW5nIHNlcnZlciIsIGUpOwoJCQkJCQkJCQl9CgkJCQkJCQkJfQoJCQkJCQkJfTsKCQkJCQkJCXQuc2V0RGFlbW9uKHRydWUpOwoJCQkJCQkJdC5zZXRQcmlvcml0eShUaHJlYWQuTk9STV9QUklPUklUWSAtIDIpOwoJCQkJCQkJdC5zdGFydCgpOwoJCQkJCQl9CgkJCQkJfQoJCQkJCQoJCQkJfQoJCQl9KTsKCQoJCQkvLyBzdG9wIHRoZSBzZXJ2ZXIKCQkJc3RvcChmYWxzZSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgcmVzdGFydGluZyBzZXJ2ZXIiLCBlKTsKCQl9Cgl9CgoKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIHRoZSBzZXJ2ZXIgaXMgaW4gYSBzdGF0ZSB0aGF0IGl0IGNhbgoJICogYmUgc3RvcHBlZC4KCSAqCgkgKiBAcmV0dXJuIGJvb2xlYW4KCSAqLwoJcHVibGljIElTdGF0dXMgY2FuU3RvcCgpIHsKCQlpZiAoZ2V0U2VydmVyU3RhdGUoKSA9PSBTVEFURV9TVE9QUEVEKQoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5lcnJvclN0b3BBbHJlYWR5U3RvcHBlZCwgbnVsbCk7CgoJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmNhblN0b3BPaywgbnVsbCk7Cgl9CgoJLyoqCgkgKiBAc2VlIElTZXJ2ZXIjc3RvcChib29sZWFuKQoJICovCglwdWJsaWMgdm9pZCBzdG9wKGJvb2xlYW4gZm9yY2UpIHsKCQlpZiAoZ2V0U2VydmVyU3RhdGUoKSA9PSBTVEFURV9TVE9QUEVEKQoJCQlyZXR1cm47CgoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlN0b3BwaW5nIHNlcnZlcjogIiArIHRvU3RyaW5nKCkpOwoKCQl0cnkgewoJCQlnZXRCZWhhdmlvdXJEZWxlZ2F0ZSgpLnN0b3AoZm9yY2UpOwoJCX0gY2F0Y2ggKFRocm93YWJsZSB0KSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgc3RvcCgpICIgKyB0b1N0cmluZygpLCB0KTsKCQl9Cgl9CgkKCS8qKgoJICogQHNlZSBJU2VydmVyI3N5bmNocm9ub3VzU3RhcnQoU3RyaW5nLCBJUHJvZ3Jlc3NNb25pdG9yKQoJICovCglwdWJsaWMgSUxhdW5jaCBzeW5jaHJvbm91c1N0YXJ0KFN0cmluZyBtb2RlMiwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNTdGFydCAxIik7CgkJZmluYWwgT2JqZWN0IG11dGV4ID0gbmV3IE9iamVjdCgpOwoJCgkJLy8gYWRkIGxpc3RlbmVyIHRvIHRoZSBzZXJ2ZXIKCQlJU2VydmVyTGlzdGVuZXIgbGlzdGVuZXIgPSBuZXcgSVNlcnZlckxpc3RlbmVyKCkgewoJCQlwdWJsaWMgdm9pZCBzZXJ2ZXJDaGFuZ2VkKFNlcnZlckV2ZW50IGV2ZW50KSB7CgkJCQlpbnQgZXZlbnRLaW5kID0gZXZlbnQuZ2V0S2luZCgpOwoJCQkJSVNlcnZlciBzZXJ2ZXIgPSBldmVudC5nZXRTZXJ2ZXIoKTsKCQkJCWlmIChldmVudEtpbmQgPT0gKFNlcnZlckV2ZW50LlNFUlZFUl9DSEFOR0UgfCBTZXJ2ZXJFdmVudC5TVEFURV9DSEFOR0UpKSB7CgkJCQkJaW50IHN0YXRlID0gc2VydmVyLmdldFNlcnZlclN0YXRlKCk7CgkJCQkJaWYgKHN0YXRlID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCB8fCBzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpIHsKCQkJCQkJLy8gbm90aWZ5IHdhaXRlcgoJCQkJCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCQkJCQl0cnkgewoJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzU3RhcnQgbm90aWZ5Iik7CgkJCQkJCQkJbXV0ZXgubm90aWZ5QWxsKCk7CgkJCQkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIG5vdGlmeWluZyBzZXJ2ZXIgc3RhcnQiLCBlKTsKCQkJCQkJCX0KCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX07CgkJYWRkU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCQoJCWZpbmFsIGludCBzZXJ2ZXJUaW1lb3V0ID0gKChTZXJ2ZXJUeXBlKSBnZXRTZXJ2ZXJUeXBlKCkpLmdldFN0YXJ0VGltZW91dCgpOwoJCWNsYXNzIFRpbWVyIHsKCQkJYm9vbGVhbiB0aW1lb3V0OwoJCQlib29sZWFuIGFscmVhZHlEb25lOwoJCX0KCQlmaW5hbCBUaW1lciB0aW1lciA9IG5ldyBUaW1lcigpOwoJCQoJCVRocmVhZCB0aHJlYWQgPSBuZXcgVGhyZWFkKCkgewoJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQl0cnkgewoJCQkJCVRocmVhZC5zbGVlcChzZXJ2ZXJUaW1lb3V0ICogMTAwMCk7CgkJCQkJaWYgKCF0aW1lci5hbHJlYWR5RG9uZSkgewoJCQkJCQl0aW1lci50aW1lb3V0ID0gdHJ1ZTsKCQkJCQkJLy8gbm90aWZ5IHdhaXRlcgoJCQkJCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IG5vdGlmeSB0aW1lb3V0Iik7CgkJCQkJCQltdXRleC5ub3RpZnlBbGwoKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igbm90aWZ5aW5nIHNlcnZlciBzdGFydCB0aW1lb3V0IiwgZSk7CgkJCQl9CgkJCX0KCQl9OwoJCXRocmVhZC5zZXREYWVtb24odHJ1ZSk7CgkJdGhyZWFkLnN0YXJ0KCk7CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IDIiKTsKCQoJCS8vIHN0YXJ0IHRoZSBzZXJ2ZXIKCQlJTGF1bmNoIGxhdW5jaDsKCQl0cnkgewoJCQlsYXVuY2ggPSBzdGFydChtb2RlMiwgbW9uaXRvcik7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCXJlbW92ZVNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkJdGltZXIuYWxyZWFkeURvbmUgPSB0cnVlOwoJCQl0aHJvdyBlOwoJCX0KCQoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzU3RhcnQgMyIpOwoJCgkJLy8gd2FpdCBmb3IgaXQhIHdhaXQgZm9yIGl0ISAuLi4KCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCXRyeSB7CgkJCQl3aGlsZSAoIXRpbWVyLnRpbWVvdXQgJiYgIShnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCB8fCBnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkpCgkJCQkJbXV0ZXgud2FpdCgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igd2FpdGluZyBmb3Igc2VydmVyIHN0YXJ0IiwgZSk7CgkJCX0KCQl9CgkJcmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCXRpbWVyLmFscmVhZHlEb25lID0gdHJ1ZTsKCQkKCQlpZiAodGltZXIudGltZW91dCkKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBOTFMuYmluZChNZXNzYWdlcy5lcnJvclN0YXJ0VGltZW91dCwgbmV3IFN0cmluZ1tdIHsgZ2V0TmFtZSgpLCBzZXJ2ZXJUaW1lb3V0ICsgIiIgfSksIG51bGwpKTsKCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE5MUy5iaW5kKE1lc3NhZ2VzLmVycm9yU3RhcnRGYWlsZWQsIGdldE5hbWUoKSksIG51bGwpKTsKCQoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzU3RhcnQgNCIpOwoJCQoJCXJldHVybiBsYXVuY2g7Cgl9CgoJLyoKCSAqIEBzZWUgSVNlcnZlciNzeW5jaHJvbm91c1Jlc3RhcnQoU3RyaW5nLCBJUHJvZ3Jlc3NNb25pdG9yKQoJICovCglwdWJsaWMgdm9pZCBzeW5jaHJvbm91c1Jlc3RhcnQoU3RyaW5nIG1vZGUyLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCQlzeW5jaHJvbm91c1N0b3AodHJ1ZSk7CgkJc3luY2hyb25vdXNTdGFydChtb2RlMiwgbW9uaXRvcik7Cgl9CgoJLyoKCSAqIEBzZWUgSVNlcnZlciNzeW5jaHJvbm91c1N0b3AoKQoJICovCglwdWJsaWMgdm9pZCBzeW5jaHJvbm91c1N0b3AoYm9vbGVhbiBmb3JjZSkgewoJCWlmIChnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuOwoJCQoJCWZpbmFsIE9iamVjdCBtdXRleCA9IG5ldyBPYmplY3QoKTsKCQoJCS8vIGFkZCBsaXN0ZW5lciB0byB0aGUgc2VydmVyCgkJSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IElTZXJ2ZXJMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgc2VydmVyQ2hhbmdlZChTZXJ2ZXJFdmVudCBldmVudCkgewoJCQkJaW50IGV2ZW50S2luZCA9IGV2ZW50LmdldEtpbmQoKTsKCQkJCUlTZXJ2ZXIgc2VydmVyID0gZXZlbnQuZ2V0U2VydmVyKCk7CgkJCQlpZiAoZXZlbnRLaW5kID09IChTZXJ2ZXJFdmVudC5TRVJWRVJfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFKSkgewoJCQkJCWludCBzdGF0ZSA9IHNlcnZlci5nZXRTZXJ2ZXJTdGF0ZSgpOwoJCQkJCWlmIChTZXJ2ZXIudGhpcyA9PSBzZXJ2ZXIgJiYgc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKSB7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJdHJ5IHsKCQkJCQkJCQltdXRleC5ub3RpZnlBbGwoKTsKCQkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igbm90aWZ5aW5nIHNlcnZlciBzdG9wIiwgZSk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCWFkZFNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkKCQljbGFzcyBUaW1lciB7CgkJCWJvb2xlYW4gdGltZW91dDsKCQkJYm9vbGVhbiBhbHJlYWR5RG9uZTsKCQl9CgkJZmluYWwgVGltZXIgdGltZXIgPSBuZXcgVGltZXIoKTsKCQkKCQlUaHJlYWQgdGhyZWFkID0gbmV3IFRocmVhZCgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJdHJ5IHsKCQkJCQlUaHJlYWQuc2xlZXAoMTIwMDAwKTsKCQkJCQlpZiAoIXRpbWVyLmFscmVhZHlEb25lKSB7CgkJCQkJCXRpbWVyLnRpbWVvdXQgPSB0cnVlOwoJCQkJCQkvLyBub3RpZnkgd2FpdGVyCgkJCQkJCXN5bmNocm9uaXplZCAobXV0ZXgpIHsKCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN0b3Agbm90aWZ5IHRpbWVvdXQiKTsKCQkJCQkJCW11dGV4Lm5vdGlmeUFsbCgpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBub3RpZnlpbmcgc2VydmVyIHN0b3AgdGltZW91dCIsIGUpOwoJCQkJfQoJCQl9CgkJfTsKCQl0aHJlYWQuc2V0RGFlbW9uKHRydWUpOwoJCXRocmVhZC5zdGFydCgpOwoJCgkJLy8gc3RvcCB0aGUgc2VydmVyCgkJc3RvcChmb3JjZSk7CgkKCQkvLyB3YWl0IGZvciBpdCEgd2FpdCBmb3IgaXQhCgkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQl0cnkgewoJCQkJd2hpbGUgKCF0aW1lci50aW1lb3V0ICYmIGdldFNlcnZlclN0YXRlKCkgIT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQkJCW11dGV4LndhaXQoKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHdhaXRpbmcgZm9yIHNlcnZlciBzdG9wIiwgZSk7CgkJCX0KCQl9CgkJcmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCQoJCS8qCgkJLy9jYW4ndCB0aHJvdyBleGNlcHRpb25zCgkJaWYgKHRpbWVyLnRpbWVvdXQpCgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyQ29yZS5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yU3RhcnRGYWlsZWQiLCBnZXROYW1lKCkpLCBudWxsKSk7CgkJZWxzZQoJCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlckNvcmUuUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvclN0YXJ0RmFpbGVkIiwgZ2V0TmFtZSgpKSwgbnVsbCkpOyovCgl9CgkKCS8qKgoJICogVHJpZ2dlciBhIHJlc3RhcnQgb2YgdGhlIGdpdmVuIG1vZHVsZSBhbmQgd2FpdCB1bnRpbCBpdCBoYXMgZmluaXNoZWQgcmVzdGFydGluZy4KCSAqCgkgKiBAcGFyYW0gbW9kdWxlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5JTW9kdWxlCgkgKiBAcGFyYW0gbW9uaXRvciBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuSVByb2dyZXNzTW9uaXRvcgoJICogQGV4Y2VwdGlvbiBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuQ29yZUV4Y2VwdGlvbiAtIHRocm93biBpZiBhbiBlcnJvciBvY2N1cnMgd2hpbGUgdHJ5aW5nIHRvIHJlc3RhcnQgdGhlIG1vZHVsZQoJICovCglwdWJsaWMgdm9pZCBzeW5jaHJvbm91c1Jlc3RhcnRNb2R1bGUoZmluYWwgSU1vZHVsZVtdIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNNb2R1bGVSZXN0YXJ0IDEiKTsKCgkJZmluYWwgT2JqZWN0IG11dGV4ID0gbmV3IE9iamVjdCgpOwoJCgkJLy8gYWRkIGxpc3RlbmVyIHRvIHRoZSBtb2R1bGUKCQlJU2VydmVyTGlzdGVuZXIgbGlzdGVuZXIgPSBuZXcgSVNlcnZlckxpc3RlbmVyKCkgewoJCQlwdWJsaWMgdm9pZCBzZXJ2ZXJDaGFuZ2VkKFNlcnZlckV2ZW50IGV2ZW50KSB7CgkJCQlpbnQgZXZlbnRLaW5kID0gZXZlbnQuZ2V0S2luZCgpOwoJCQkJSVNlcnZlciBzZXJ2ZXIgPSBldmVudC5nZXRTZXJ2ZXIoKTsKCQkJCWlmIChldmVudEtpbmQgPT0gKFNlcnZlckV2ZW50Lk1PRFVMRV9DSEFOR0UgfCBTZXJ2ZXJFdmVudC5TVEFURV9DSEFOR0UpKSB7CgkJCQkJaW50IHN0YXRlID0gc2VydmVyLmdldE1vZHVsZVN0YXRlKG1vZHVsZSk7CgkJCQkJaWYgKHN0YXRlID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCB8fCBzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpIHsKCQkJCQkJLy8gbm90aWZ5IHdhaXRlcgoJCQkJCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCQkJCQl0cnkgewoJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzTW9kdWxlUmVzdGFydCBub3RpZnkiKTsKCQkJCQkJCQltdXRleC5ub3RpZnlBbGwoKTsKCQkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igbm90aWZ5aW5nIG1vZHVsZSByZXN0YXJ0IiwgZSk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCWFkZFNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkKCQkvLyBtYWtlIHN1cmUgaXQgdGltZXMgb3V0IGFmdGVyIDMwcwoJCWNsYXNzIFRpbWVyIHsKCQkJYm9vbGVhbiB0aW1lb3V0OwoJCQlib29sZWFuIGFscmVhZHlEb25lOwoJCX0KCQlmaW5hbCBUaW1lciB0aW1lciA9IG5ldyBUaW1lcigpOwoJCQoJCVRocmVhZCB0aHJlYWQgPSBuZXcgVGhyZWFkKCkgewoJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQl0cnkgewoJCQkJCVRocmVhZC5zbGVlcCgzMDAwMCk7CgkJCQkJaWYgKCF0aW1lci5hbHJlYWR5RG9uZSkgewoJCQkJCQl0aW1lci50aW1lb3V0ID0gdHJ1ZTsKCQkJCQkJLy8gbm90aWZ5IHdhaXRlcgoJCQkJCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c01vZHVsZVJlc3RhcnQgbm90aWZ5IHRpbWVvdXQiKTsKCQkJCQkJCW11dGV4Lm5vdGlmeUFsbCgpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBub3RpZnlpbmcgbW9kdWxlIHJlc3RhcnQgdGltZW91dCIsIGUpOwoJCQkJfQoJCQl9CgkJfTsKCQl0aHJlYWQuc2V0RGFlbW9uKHRydWUpOwoJCXRocmVhZC5zdGFydCgpOwoJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNNb2R1bGVSZXN0YXJ0IDIiKTsKCQoJCS8vIHJlc3RhcnQgdGhlIG1vZHVsZQoJCXRyeSB7CgkJCWdldEJlaGF2aW91ckRlbGVnYXRlKCkucmVzdGFydE1vZHVsZShtb2R1bGUsIG1vbml0b3IpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQlyZW1vdmVTZXJ2ZXJMaXN0ZW5lcihsaXN0ZW5lcik7CgkJCXRocm93IGU7CgkJfQoJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNNb2R1bGVSZXN0YXJ0IDMiKTsKCQoJCS8vIHdhaXQgZm9yIGl0ISB3YWl0IGZvciBpdCEgLi4uCgkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQl0cnkgewoJCQkJd2hpbGUgKCF0aW1lci50aW1lb3V0ICYmICEoZ2V0TW9kdWxlU3RhdGUobW9kdWxlKSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQgfHwgZ2V0TW9kdWxlU3RhdGUobW9kdWxlKSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpKQoJCQkJCW11dGV4LndhaXQoKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHdhaXRpbmcgZm9yIHNlcnZlciBzdGFydCIsIGUpOwoJCQl9CgkJfQoJCXJlbW92ZVNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQlpZiAodGltZXIudGltZW91dCkKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBOTFMuYmluZChNZXNzYWdlcy5lcnJvck1vZHVsZVJlc3RhcnRGYWlsZWQsIGdldE5hbWUoKSksIG51bGwpKTsKCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKGdldE1vZHVsZVN0YXRlKG1vZHVsZSkgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE5MUy5iaW5kKE1lc3NhZ2VzLmVycm9yTW9kdWxlUmVzdGFydEZhaWxlZCwgZ2V0TmFtZSgpKSwgbnVsbCkpOwoJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNNb2R1bGVSZXN0YXJ0IDQiKTsKCX0KCglwdWJsaWMgSVBhdGggZ2V0VGVtcERpcmVjdG9yeSgpIHsKCQlyZXR1cm4gU2VydmVyUGx1Z2luLmdldEluc3RhbmNlKCkuZ2V0VGVtcERpcmVjdG9yeShnZXRJZCgpKTsKCX0KCglwcm90ZWN0ZWQgU3RyaW5nIGdldFhNTFJvb3QoKSB7CgkJcmV0dXJuICJzZXJ2ZXIiOwoJfQoJCglwcm90ZWN0ZWQgdm9pZCBsb2FkU3RhdGUoSU1lbWVudG8gbWVtZW50bykgewoJCS8qU3RyaW5nIHNlcnZlclR5cGVJZCA9IG1lbWVudG8uZ2V0U3RyaW5nKCJzZXJ2ZXItdHlwZS1pZCIpOwoJCXNlcnZlclR5cGUgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlclR5cGUoc2VydmVyVHlwZUlkKTsKCQkKCQlTdHJpbmcgcnVudGltZUlkID0gbWVtZW50by5nZXRTdHJpbmcoInJ1bnRpbWUtaWQiKTsKCQlydW50aW1lID0gU2VydmVyQ29yZS5nZXRSZXNvdXJjZU1hbmFnZXIoKS5nZXRSdW50aW1lKHJ1bnRpbWVJZCk7CgkJCgkJU3RyaW5nIGNvbmZpZ3VyYXRpb25JZCA9IG1lbWVudG8uZ2V0U3RyaW5nKCJjb25maWd1cmF0aW9uLWlkIik7CgkJY29uZmlndXJhdGlvbiA9IFNlcnZlckNvcmUuZ2V0UmVzb3VyY2VNYW5hZ2VyKCkuZ2V0U2VydmVyQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uSWQpOyovCgkJcmVzb2x2ZSgpOwoJfQoJCglwcm90ZWN0ZWQgdm9pZCByZXNvbHZlKCkgewoJCUlTZXJ2ZXJUeXBlIG9sZFNlcnZlclR5cGUgPSBzZXJ2ZXJUeXBlOwoJCVN0cmluZyBzZXJ2ZXJUeXBlSWQgPSBnZXRBdHRyaWJ1dGUoInNlcnZlci10eXBlLWlkIiwgKFN0cmluZyludWxsKTsKCQlpZiAoc2VydmVyVHlwZUlkICE9IG51bGwpCgkJCXNlcnZlclR5cGUgPSBTZXJ2ZXJDb3JlLmZpbmRTZXJ2ZXJUeXBlKHNlcnZlclR5cGVJZCk7CgkJZWxzZQoJCQlzZXJ2ZXJUeXBlID0gbnVsbDsKCQlpZiAoc2VydmVyVHlwZSAhPSBudWxsICYmICFzZXJ2ZXJUeXBlLmVxdWFscyhvbGRTZXJ2ZXJUeXBlKSkKCQkJc2VydmVyU3RhdGUgPSAoKFNlcnZlclR5cGUpc2VydmVyVHlwZSkuZ2V0SW5pdGlhbFN0YXRlKCk7CgkJCgkJU3RyaW5nIHJ1bnRpbWVJZCA9IGdldEF0dHJpYnV0ZShSVU5USU1FX0lELCAoU3RyaW5nKW51bGwpOwoJCWlmIChydW50aW1lSWQgIT0gbnVsbCkKCQkJcnVudGltZSA9IFNlcnZlckNvcmUuZmluZFJ1bnRpbWUocnVudGltZUlkKTsKCQkKCQlTdHJpbmcgY29uZmlnUGF0aCA9IGdldEF0dHJpYnV0ZShDT05GSUdVUkFUSU9OX0lELCAoU3RyaW5nKW51bGwpOwoJCWNvbmZpZ3VyYXRpb24gPSBudWxsOwoJCWlmIChjb25maWdQYXRoICE9IG51bGwpCgkJCWNvbmZpZ3VyYXRpb24gPSBSZXNvdXJjZXNQbHVnaW4uZ2V0V29ya3NwYWNlKCkuZ2V0Um9vdCgpLmdldEZvbGRlcihuZXcgUGF0aChjb25maWdQYXRoKSk7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgc2V0SW50ZXJuYWwoU2VydmVyV29ya2luZ0NvcHkgd2MpIHsKCQltYXAgPSB3Yy5tYXA7CgkJY29uZmlndXJhdGlvbiA9IHdjLmNvbmZpZ3VyYXRpb247CgkJcnVudGltZSA9IHdjLnJ1bnRpbWU7CgkJc2VydmVyU3luY1N0YXRlID0gd2Muc2VydmVyU3luY1N0YXRlOwoJCS8vcmVzdGFydE5lZWRlZCA9IHdjLnJlc3RhcnROZWVkZWQ7CgkJc2VydmVyVHlwZSA9IHdjLnNlcnZlclR5cGU7CgkJbW9kdWxlcyA9IHdjLm1vZHVsZXM7CgoJCS8vIGNhbiBuZXZlciBtb2RpZnkgdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzIHZpYSB0aGUgd29ya2luZyBjb3B5CgkJLy9zZXJ2ZXJTdGF0ZSA9IHdjLnNlcnZlclN0YXRlOwoJCWRlbGVnYXRlID0gd2MuZGVsZWdhdGU7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgc2F2ZVN0YXRlKElNZW1lbnRvIG1lbWVudG8pIHsKCQlpZiAoc2VydmVyVHlwZSAhPSBudWxsKQoJCQltZW1lbnRvLnB1dFN0cmluZygic2VydmVyLXR5cGUiLCBzZXJ2ZXJUeXBlLmdldElkKCkpOwoKCQlpZiAoY29uZmlndXJhdGlvbiAhPSBudWxsKQoJCQltZW1lbnRvLnB1dFN0cmluZyhDT05GSUdVUkFUSU9OX0lELCBjb25maWd1cmF0aW9uLmdldEZ1bGxQYXRoKCkudG9TdHJpbmcoKSk7CgkJZWxzZQoJCQltZW1lbnRvLnB1dFN0cmluZyhDT05GSUdVUkFUSU9OX0lELCBudWxsKTsKCQkKCQlpZiAocnVudGltZSAhPSBudWxsKQoJCQltZW1lbnRvLnB1dFN0cmluZyhSVU5USU1FX0lELCBydW50aW1lLmdldElkKCkpOwoJCWVsc2UKCQkJbWVtZW50by5wdXRTdHJpbmcoUlVOVElNRV9JRCwgbnVsbCk7Cgl9CgoJLypwdWJsaWMgdm9pZCB1cGRhdGVDb25maWd1cmF0aW9uKCkgewoJCXRyeSB7CgkJCWdldERlbGVnYXRlKG51bGwpLnVwZGF0ZUNvbmZpZ3VyYXRpb24oKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIHVwZGF0ZUNvbmZpZ3VyYXRpb24oKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJfQoJfSovCgkKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklTZXJ2ZXJDb25maWd1cmF0aW9uI2Nhbk1vZGlmeU1vZHVsZShvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUubW9kZWwuSU1vZHVsZSkKCSAqLwoJcHVibGljIElTdGF0dXMgY2FuTW9kaWZ5TW9kdWxlcyhJTW9kdWxlW10gYWRkLCBJTW9kdWxlW10gcmVtb3ZlLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQl0cnkgewoJCQlyZXR1cm4gZ2V0RGVsZWdhdGUoKS5jYW5Nb2RpZnlNb2R1bGVzKGFkZCwgcmVtb3ZlKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIGNhbk1vZGlmeU1vZHVsZXMoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXJldHVybiBudWxsOwoJCX0KCX0KCgkvKiAobm9uLUphdmFkb2MpCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5JU2VydmVyI2dldE1vZHVsZXMoKQoJICovCglwdWJsaWMgSU1vZHVsZVtdIGdldE1vZHVsZXMoKSB7CgkJaWYgKG1vZHVsZXMgPT0gbnVsbCkgewoJCQkvLyBjb252ZXJ0IGZyb20gYXR0cmlidXRlCgkJCUxpc3QgbGlzdCA9IGdldEF0dHJpYnV0ZShNT0RVTEVfTElTVCwgKExpc3QpIG51bGwpOwoJCQlpZiAobGlzdCA9PSBudWxsKQoJCQkJbGlzdCA9IG5ldyBBcnJheUxpc3QoMSk7CgkJCQoJCQltb2R1bGVzID0gbmV3IEFycmF5TGlzdChsaXN0LnNpemUoKSArIDEpOwoJCQlJdGVyYXRvciBpdGVyYXRvciA9IGxpc3QuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQkJU3RyaW5nIG1vZHVsZVN0ciA9IChTdHJpbmcpIGl0ZXJhdG9yLm5leHQoKTsKCQkJCUlNb2R1bGUgbW9kdWxlID0gU2VydmVyVXRpbC5nZXRNb2R1bGUobW9kdWxlU3RyKTsKCQkJCWlmIChtb2R1bGUgIT0gbnVsbCkKCQkJCQltb2R1bGVzLmFkZChtb2R1bGUpOwoJCQl9CgkJfSBlbHNlIHsKCQkJLy8gdmVyaWZ5IG1vZHVsZXMgYXJlIHN0aWxsIGF2YWlsYWJsZQoJCQlMaXN0IHJlbW92ZSA9IG5ldyBBcnJheUxpc3QoKTsKCQkJSXRlcmF0b3IgaXRlcmF0b3IgPSBtb2R1bGVzLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJCUlNb2R1bGUgbW9kdWxlID0gKElNb2R1bGUpIGl0ZXJhdG9yLm5leHQoKTsKCQkJCWlmIChTZXJ2ZXJVdGlsLmdldE1vZHVsZShtb2R1bGUuZ2V0SWQoKSkgPT0gbnVsbCkKCQkJCQlyZW1vdmUuYWRkKG1vZHVsZSk7CgkJCX0KCQkJCgkJCWl0ZXJhdG9yID0gcmVtb3ZlLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJCW1vZHVsZXMucmVtb3ZlKGl0ZXJhdG9yLm5leHQoKSk7CgkJCX0KCQl9CgkJCgkJSU1vZHVsZVtdIG1vZHVsZXMyID0gbmV3IElNb2R1bGVbbW9kdWxlcy5zaXplKCldOwoJCW1vZHVsZXMudG9BcnJheShtb2R1bGVzMik7CgkJcmV0dXJuIG1vZHVsZXMyOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklTZXJ2ZXIjZ2V0TW9kdWxlU3RhdGUoKQoJICovCglwdWJsaWMgaW50IGdldE1vZHVsZVN0YXRlKElNb2R1bGVbXSBtb2R1bGUpIHsKCQl0cnkgewoJCQlJbnRlZ2VyIGluID0gKEludGVnZXIpIG1vZHVsZVN0YXRlLmdldChnZXRLZXkobW9kdWxlKSk7CgkJCWlmIChpbiAhPSBudWxsKQoJCQkJcmV0dXJuIGluLmludFZhbHVlKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCXJldHVybiBTVEFURV9VTktOT1dOOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklTZXJ2ZXIjZ2V0TW9kdWxlU3RhdGUoKQoJICovCglwdWJsaWMgaW50IGdldE1vZHVsZVB1Ymxpc2hTdGF0ZShJTW9kdWxlW10gbW9kdWxlKSB7CgkJdHJ5IHsKCQkJSW50ZWdlciBpbiA9IChJbnRlZ2VyKSBtb2R1bGVQdWJsaXNoU3RhdGUuZ2V0KGdldEtleShtb2R1bGUpKTsKCQkJaWYgKGluICE9IG51bGwpCgkJCQlyZXR1cm4gaW4uaW50VmFsdWUoKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJcmV0dXJuIFBVQkxJU0hfU1RBVEVfVU5LTk9XTjsKCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI2dldENoaWxkTW9kdWxlKElNb2R1bGVbXSkKCSAqLwoJcHVibGljIElNb2R1bGVbXSBnZXRDaGlsZE1vZHVsZXMoSU1vZHVsZVtdIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJdHJ5IHsKCQkJcmV0dXJuIGdldERlbGVnYXRlKCkuZ2V0Q2hpbGRNb2R1bGVzKG1vZHVsZSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBnZXRDaGlsZE1vZHVsZXMoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXJldHVybiBudWxsOwoJCX0KCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI2dldFJvb3RNb2R1bGVzKElNb2R1bGUpCgkgKi8KCXB1YmxpYyBJTW9kdWxlW10gZ2V0Um9vdE1vZHVsZXMoSU1vZHVsZSBtb2R1bGUsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXRyeSB7CgkJCXJldHVybiBnZXREZWxlZ2F0ZSgpLmdldFJvb3RNb2R1bGVzKG1vZHVsZSk7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBzZSkgewoJCQkvL1RyYWNlLnRyYWNlKFRyYWNlLkZJTkVSLCAiQ29yZUV4Y2VwdGlvbiBjYWxsaW5nIGRlbGVnYXRlIGdldFBhcmVudE1vZHVsZXMoKSAiICsgdG9TdHJpbmcoKSArICI6ICIgKyBzZS5nZXRNZXNzYWdlKCkpOwoJCQl0aHJvdyBzZTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIGdldFBhcmVudE1vZHVsZXMoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXJldHVybiBudWxsOwoJCX0KCX0KCQoJLyoKCSAqIAoJICovCgkvKnB1YmxpYyBib29sZWFuIGhhc1J1bnRpbWUoKSB7CgkJdHJ5IHsKCQkJcmV0dXJuIGdldERlbGVnYXRlKCkucmVxdWlyZXNSdW50aW1lKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSByZXF1aXJlc1J1bnRpbWUoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXJldHVybiBmYWxzZTsKCQl9Cgl9Ki8KCQoJLyoqCgkgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIGdpdmVuIG1vZHVsZSBjYW4gYmUgcmVzdGFydGVkLgoJICoKCSAqIEBwYXJhbSBtb2R1bGUgdGhlIG1vZHVsZQoJICogQHJldHVybiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgZ2l2ZW4gbW9kdWxlIGNhbiBiZQoJICogICAgcmVzdGFydGVkLCBhbmQgPGNvZGU+ZmFsc2U8L2NvZGU+IG90aGVyd2lzZQoJICovCglwdWJsaWMgSVN0YXR1cyBjYW5SZXN0YXJ0TW9kdWxlKElNb2R1bGVbXSBtb2R1bGUpIHsKCQl0cnkgewoJCQlib29sZWFuIGIgPSBnZXRCZWhhdmlvdXJEZWxlZ2F0ZSgpLmNhblJlc3RhcnRNb2R1bGUobW9kdWxlKTsKCQkJaWYgKGIpCgkJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5jYW5SZXN0YXJ0TW9kdWxlT2ssIG51bGwpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgY2FuUmVzdGFydFJ1bnRpbWUoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJfQoJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yUmVzdGFydE1vZHVsZSwgbnVsbCk7Cgl9CgoJLyoqCgkgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gbW9kdWxlIGlzIGluIHN5bmMgb24gdGhlIHNlcnZlci4gSXQgc2hvdWxkCgkgKiByZXR1cm4gdHJ1ZSBpZiB0aGUgbW9kdWxlIHNob3VsZCBiZSByZXN0YXJ0ZWQgKGlzIG91dCBvZgoJICogc3luYykgb3IgZmFsc2UgaWYgdGhlIG1vZHVsZSBkb2VzIG5vdCBuZWVkIHRvIGJlIHJlc3RhcnRlZC4KCSAqCgkgKiBAcGFyYW0gbW9kdWxlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC5JTW9kdWxlCgkgKiBAcmV0dXJuIGJvb2xlYW4KCSAqLwoJcHVibGljIGJvb2xlYW4gZ2V0TW9kdWxlUmVzdGFydFN0YXRlKElNb2R1bGVbXSBtb2R1bGUpIHsKCQl0cnkgewoJCQlCb29sZWFuIGIgPSAoQm9vbGVhbikgbW9kdWxlUmVzdGFydFN0YXRlLmdldChnZXRLZXkobW9kdWxlKSk7CgkJCWlmIChiICE9IG51bGwpCgkJCQlyZXR1cm4gYi5ib29sZWFuVmFsdWUoKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJcmV0dXJuIGZhbHNlOwoJfQoKCS8qCgkgKiBAc2VlIElTZXJ2ZXIjcmVzdGFydE1vZHVsZShJTW9kdWxlW10sIElQcm9ncmVzc01vbml0b3IpCgkgKi8KCXB1YmxpYyB2b2lkIHJlc3RhcnRNb2R1bGUoSU1vZHVsZVtdIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJdHJ5IHsKCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKS5yZXN0YXJ0TW9kdWxlKG1vZHVsZSwgbW9uaXRvcik7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSByZXN0YXJ0TW9kdWxlKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCX0KCX0KCQoJLyoqCgkgKiBSZXR1cm5zIGFuIGFycmF5IG9mIElTZXJ2ZXJQb3J0cyB0aGF0IHRoaXMgc2VydmVyIGhhcy4KCSAqCgkgKiBAcmV0dXJuIGEgcG9zc2libHkgZW1wdHkgYXJyYXkgb2Ygc2VydmVycyBwb3J0cwoJICovCglwdWJsaWMgU2VydmVyUG9ydFtdIGdldFNlcnZlclBvcnRzKCkgewoJCXRyeSB7CgkJCXJldHVybiBnZXREZWxlZ2F0ZSgpLmdldFNlcnZlclBvcnRzKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBnZXRTZXJ2ZXJQb3J0cygpICIgKyB0b1N0cmluZygpLCBlKTsKCQkJcmV0dXJuIG51bGw7CgkJfQoJfQoJCgkvKioKCSAqIFZpc2l0IGFsbCB0aGUgbW9kdWxlcyBpbiB0aGUgc2VydmVyIHdpdGggdGhlIGdpdmVuIG1vZHVsZSB2aXNpdG9yLgoJICogCgkgKiBAcGFyYW0gdmlzaXRvciB0aGUgdmlzaXRvcgoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yLCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiBwcm9ncmVzcwoJICogICAgcmVwb3J0aW5nIGFuZCBjYW5jZWxsYXRpb24gYXJlIG5vdCBkZXNpcmVkCgkgKi8KCXB1YmxpYyB2b2lkIHZpc2l0KElNb2R1bGVWaXNpdG9yIHZpc2l0b3IsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCUlNb2R1bGVbXSBtb2R1bGVzMiA9IGdldE1vZHVsZXMoKTsKCQlpZiAobW9kdWxlczIgIT0gbnVsbCkgeyAKCQkJaW50IHNpemUgPSBtb2R1bGVzMi5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlpZiAoIXZpc2l0TW9kdWxlKG5ldyBJTW9kdWxlW10geyBtb2R1bGVzMltpXSB9LCB2aXNpdG9yLCBtb25pdG9yKSkKCQkJCQlyZXR1cm47CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgdG8ga2VlcCB2aXNpdGluZywgYW5kIGZhbHNlIHRvIHN0b3AuCgkgKiAKCSAqIEBwYXJhbSBtb25pdG9yIGEgcHJvZ3Jlc3MgbW9uaXRvciwgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgcHJvZ3Jlc3MKCSAqICAgIHJlcG9ydGluZyBhbmQgY2FuY2VsbGF0aW9uIGFyZSBub3QgZGVzaXJlZAoJICovCglwcml2YXRlIGJvb2xlYW4gdmlzaXRNb2R1bGUoSU1vZHVsZVtdIG1vZHVsZSwgSU1vZHVsZVZpc2l0b3IgdmlzaXRvciwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQlyZXR1cm4gdHJ1ZTsKCQkKCQlpZiAoIXZpc2l0b3IudmlzaXQobW9kdWxlKSkKCQkJcmV0dXJuIGZhbHNlOwoJCQoJCUlNb2R1bGVbXSBjaGlsZHJlbiA9IGdldENoaWxkTW9kdWxlcyhtb2R1bGUsIG1vbml0b3IpOwoJCWlmIChjaGlsZHJlbiAhPSBudWxsKSB7CgkJCWludCBzaXplID0gY2hpbGRyZW4ubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJSU1vZHVsZVtdIG1vZHVsZTIgPSBuZXcgSU1vZHVsZVttb2R1bGUubGVuZ3RoICsgMV07CgkJCQlTeXN0ZW0uYXJyYXljb3B5KG1vZHVsZSwgMCwgbW9kdWxlMiwgMCwgbW9kdWxlLmxlbmd0aCk7CgkJCQltb2R1bGUyW21vZHVsZS5sZW5ndGhdID0gY2hpbGRyZW5baV07CgkJCQkKCQkJCWlmICghdmlzaXRNb2R1bGUobW9kdWxlMiwgdmlzaXRvciwgbW9uaXRvcikpCgkJCQkJcmV0dXJuIGZhbHNlOwoJCQl9CgkJfQoJCQoJCXJldHVybiB0cnVlOwoJfQoJCglwcml2YXRlIFN0cmluZyBnZXRLZXkoSU1vZHVsZVtdIG1vZHVsZSkgewoJCVN0cmluZ0J1ZmZlciBzYiA9IG5ldyBTdHJpbmdCdWZmZXIoKTsKCQkKCQlpZiAobW9kdWxlICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBtb2R1bGUubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGkgIT0gMCkKCQkJCQlzYi5hcHBlbmQoIiMiKTsKCQkJCXNiLmFwcGVuZChtb2R1bGVbaV0uZ2V0SWQoKSk7CgkJCX0KCQl9CgkJCgkJcmV0dXJuIHNiLnRvU3RyaW5nKCk7Cgl9CgkKCXB1YmxpYyB2b2lkIHNldE1vZHVsZVN0YXR1cyhJTW9kdWxlW10gbW9kdWxlLCBJU3RhdHVzIHN0YXR1cykgewoJCW1vZHVsZVN0YXR1cy5wdXQoZ2V0S2V5KG1vZHVsZSksIHN0YXR1cyk7CgkJLy9maXJlU2VydmVyTW9kdWxlU3RhdGVDaGFuZ2VFdmVudChtb2R1bGUpOwoJfQoJCglwdWJsaWMgSVN0YXR1cyBnZXRNb2R1bGVTdGF0dXMoSU1vZHVsZVtdIG1vZHVsZSkgewoJCXRyeSB7CgkJCXJldHVybiAoSVN0YXR1cykgbW9kdWxlU3RhdHVzLmdldChnZXRLZXkobW9kdWxlKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJcmV0dXJuIG51bGw7CgkJfQoJfQoJCglwdWJsaWMgdm9pZCBzZXRTZXJ2ZXJTdGF0dXMoSVN0YXR1cyBzdGF0dXMpIHsKCQlzZXJ2ZXJTdGF0dXMgPSBzdGF0dXM7CgkJLy9maXJlU2VydmVyU3RhdGVDaGFuZ2VFdmVudCgpOwoJfQoJCglwdWJsaWMgSVN0YXR1cyBnZXRTZXJ2ZXJTdGF0dXMoKSB7CgkJcmV0dXJuIHNlcnZlclN0YXR1czsKCX0KfQ==