LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbDsKCmltcG9ydCBqYXZhLnV0aWwuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRmlsZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLklGb2xkZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5SZXNvdXJjZXNQbHVnaW47CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5qb2JzLkpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLmRlYnVnLmNvcmUuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5vc2dpLnV0aWwuTkxTOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLio7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUubW9kZWwuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS51dGlsLlNvY2tldFV0aWw7Ci8qKgogKiAKICovCnB1YmxpYyBjbGFzcyBTZXJ2ZXIgZXh0ZW5kcyBCYXNlIGltcGxlbWVudHMgSVNlcnZlciB7CgkvKioKCSAqIFNlcnZlciBpZCBhdHRyaWJ1dGUgKHZhbHVlICJzZXJ2ZXItaWQiKSBvZiBsYXVuY2ggY29uZmlndXJhdGlvbnMuCgkgKiBUaGlzIGF0dHJpYnV0ZSBpcyB1c2VkIHRvIHRhZyBhIGxhdW5jaCBjb25maWd1cmF0aW9uIHdpdGggdGhlCgkgKiBpZCBvZiB0aGUgY29ycmVzcG9uZGluZyBzZXJ2ZXIuCgkgKiAKCSAqIEBzZWUgSUxhdW5jaENvbmZpZ3VyYXRpb24KCSAqLwoJcHVibGljIHN0YXRpYyBmaW5hbCBTdHJpbmcgQVRUUl9TRVJWRVJfSUQgPSAic2VydmVyLWlkIjsKCglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIExpc3QgRU1QVFlfTElTVCA9IG5ldyBBcnJheUxpc3QoMCk7CgkKCS8qKgoJICogRmlsZSBleHRlbnNpb24gKHZhbHVlICJzZXJ2ZXIiKSBmb3Igc2VyaWFsaXplZCByZXByZXNlbnRhdGlvbiBvZgoJICogc2VydmVyIGluc3RhbmNlcy4KCSAqIDxwPgoJICogW2lzc3VlOiBXaGF0IGlzIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoaXMgZmlsZSBleHRlbnNpb24gYW5kCgkgKiB0aGUgZmlsZSBwYXNzZWQgdG8gSVNlcnZlclR5cGUuY3JlYXRlKC4uLikgb3IgcmV0dXJuZWQgYnkKCSAqIElTZXJ2ZXIuZ2V0RmlsZSgpPyBUaGF0IGlzLCBhcmUgc2VydmVyIGZpbGVzIGV4cGVjdGVkIHRvIGVuZAoJICogaW4gIi5zZXJ2ZXIiLCBvciBpcyB0aGlzIGp1c3QgYSBkZWZhdWx0PyBJZiB0aGUgZm9ybWVyCgkgKiAoYXMgSSBzdXNwZWN0KSwgdGhlbiBJU2VydmVyVHlwZS5jcmVhdGUgbmVlZHMgdG8gc2F5IHNvLAoJICogYW5kIHRoZSBpbXBsZW1lbnRhdGlvbiBzaG91bGQgZW5mb3JjZSB0aGUgcmVzdHJpY3Rpb24uXQoJICogPC9wPgoJICovCglwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBGSUxFX0VYVEVOU0lPTiA9ICJzZXJ2ZXIiOwoJCglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZyBQUk9QX0hPU1ROQU1FID0gImhvc3RuYW1lIjsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIFNFUlZFUl9JRCA9ICJzZXJ2ZXItaWQiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgUlVOVElNRV9JRCA9ICJydW50aW1lLWlkIjsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIENPTkZJR1VSQVRJT05fSUQgPSAiY29uZmlndXJhdGlvbi1pZCI7Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZyBNT0RVTEVfTElTVCA9ICJtb2R1bGVzIjsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIFBST1BfQVVUT19QVUJMSVNIX1RJTUUgPSAiYXV0by1wdWJsaXNoLXRpbWUiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgUFJPUF9BVVRPX1BVQkxJU0hfREVGQVVMVCA9ICJhdXRvLXB1Ymxpc2gtZGVmYXVsdCI7CgoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBjaGFyW10gSU5WQUxJRF9DSEFSUyA9IG5ldyBjaGFyW10geydcXCcsICcvJywgJzonLCAnKicsICc/JywgJyInLCAnPCcsICc+JywgJ3wnLCAnXDAnLCAnQCcsICcmJ307CgoJcHJvdGVjdGVkIElTZXJ2ZXJUeXBlIHNlcnZlclR5cGU7Cglwcm90ZWN0ZWQgU2VydmVyRGVsZWdhdGUgZGVsZWdhdGU7Cglwcm90ZWN0ZWQgU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUgYmVoYXZpb3VyRGVsZWdhdGU7CgoJcHJvdGVjdGVkIElSdW50aW1lIHJ1bnRpbWU7Cglwcm90ZWN0ZWQgSUZvbGRlciBjb25maWd1cmF0aW9uOwoJCgkvLyB0aGUgbGlzdCBvZiBtb2R1bGVzIHRoYXQgYXJlIHRvIGJlIHB1Ymxpc2hlZCB0byB0aGUgc2VydmVyCglwcm90ZWN0ZWQgTGlzdCBtb2R1bGVzOwoJCgkvLyB0cmFuc2llbnQgZmllbGRzCglwcm90ZWN0ZWQgdHJhbnNpZW50IFN0cmluZyBtb2RlID0gSUxhdW5jaE1hbmFnZXIuUlVOX01PREU7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGludCBzZXJ2ZXJTdGF0ZSA9IFNUQVRFX1VOS05PV047Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGludCBzZXJ2ZXJTeW5jU3RhdGU7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGJvb2xlYW4gc2VydmVyUmVzdGFydE5lZWRlZDsKCglwcm90ZWN0ZWQgdHJhbnNpZW50IE1hcCBtb2R1bGVTdGF0ZSA9IG5ldyBIYXNoTWFwKCk7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IE1hcCBtb2R1bGVQdWJsaXNoU3RhdGUgPSBuZXcgSGFzaE1hcCgpOwoJcHJvdGVjdGVkIHRyYW5zaWVudCBNYXAgbW9kdWxlUmVzdGFydFN0YXRlID0gbmV3IEhhc2hNYXAoKTsKCQoJcHJvdGVjdGVkIHRyYW5zaWVudCBJU3RhdHVzIHNlcnZlclN0YXR1czsKCXByb3RlY3RlZCB0cmFuc2llbnQgTWFwIG1vZHVsZVN0YXR1cyA9IG5ldyBIYXNoTWFwKCk7CgoJcHJvdGVjdGVkIHRyYW5zaWVudCBTZXJ2ZXJQdWJsaXNoSW5mbyBwdWJsaXNoSW5mbzsKCXByb3RlY3RlZCB0cmFuc2llbnQgQXV0b1B1Ymxpc2hUaHJlYWQgYXV0b1B1Ymxpc2hUaHJlYWQ7CgovKglwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmdbXSBzdGF0ZVN0cmluZ3MgPSBuZXcgU3RyaW5nW10gewoJCSJ1bmtub3duIiwgInN0YXJ0aW5nIiwgInN0YXJ0ZWQiLCAic3RhcnRlZF9kZWJ1ZyIsCgkJInN0b3BwaW5nIiwgInN0b3BwZWQiLCAic3RhcnRlZF91bnN1cHBvcnRlZCIsICJzdGFydGVkX3Byb2ZpbGUiCgl9OyovCgkKCS8vIHB1Ymxpc2ggbGlzdGVuZXJzCglwcm90ZWN0ZWQgdHJhbnNpZW50IExpc3QgcHVibGlzaExpc3RlbmVyczsKCQoJLy8gU2VydmVyIGxpc3RlbmVycwoJcHJvdGVjdGVkIHRyYW5zaWVudCBTZXJ2ZXJOb3RpZmljYXRpb25NYW5hZ2VyIG5vdGlmaWNhdGlvbk1hbmFnZXI7CgkKCXB1YmxpYyBjbGFzcyBBdXRvUHVibGlzaFRocmVhZCBleHRlbmRzIFRocmVhZCB7CgkJcHVibGljIGJvb2xlYW4gc3RvcDsKCQlwdWJsaWMgaW50IHRpbWUgPSAwOyAKCQkKCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkF1dG8tcHVibGlzaCB0aHJlYWQgc3RhcnRpbmcgZm9yICIgKyBTZXJ2ZXIudGhpcyArICIgLSAiICsgdGltZSArICJzIik7CgkJCWlmIChzdG9wKQoJCQkJcmV0dXJuOwoJCQkKCQkJdHJ5IHsKCQkJCXNsZWVwKHRpbWUgKiAxMDAwKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCS8vIGlnbm9yZQoJCQl9CgkJCQoJCQlpZiAoc3RvcCkKCQkJCXJldHVybjsKCQkJCgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkF1dG8tcHVibGlzaCB0aHJlYWQgcHVibGlzaGluZyAiICsgU2VydmVyLnRoaXMpOwoKCQkJUHVibGlzaFNlcnZlckpvYiBwdWJsaXNoSm9iID0gbmV3IFB1Ymxpc2hTZXJ2ZXJKb2IoU2VydmVyLnRoaXMsIElTZXJ2ZXIuUFVCTElTSF9BVVRPLCBmYWxzZSk7CgkJCXB1Ymxpc2hKb2Iuc2NoZWR1bGUoKTsKCQl9Cgl9CgoJLy8gd29ya2luZyBjb3B5LCBsb2FkZWQgcmVzb3VyY2UKCXB1YmxpYyBTZXJ2ZXIoSUZpbGUgZmlsZSkgewoJCXN1cGVyKGZpbGUpOwoJCW1hcC5wdXQoUFJPUF9IT1NUTkFNRSwgImxvY2FsaG9zdCIpOwoJfQoKCS8vIGNyZWF0aW9uICh3b3JraW5nIGNvcHkpCglwdWJsaWMgU2VydmVyKFN0cmluZyBpZCwgSUZpbGUgZmlsZSwgSVJ1bnRpbWUgcnVudGltZSwgSVNlcnZlclR5cGUgc2VydmVyVHlwZSkgewoJCXN1cGVyKGZpbGUsIGlkKTsKCQl0aGlzLnJ1bnRpbWUgPSBydW50aW1lOwoJCXRoaXMuc2VydmVyVHlwZSA9IHNlcnZlclR5cGU7CgkJbWFwLnB1dCgic2VydmVyLXR5cGUtaWQiLCBzZXJ2ZXJUeXBlLmdldElkKCkpOwoJCW1hcC5wdXQoUFJPUF9IT1NUTkFNRSwgImxvY2FsaG9zdCIpOwoJCWlmIChydW50aW1lICE9IG51bGwgJiYgcnVudGltZS5nZXRSdW50aW1lVHlwZSgpICE9IG51bGwpIHsKCQkJU3RyaW5nIG5hbWUgPSBydW50aW1lLmdldFJ1bnRpbWVUeXBlKCkuZ2V0TmFtZSgpOwoJCQltYXAucHV0KFBST1BfTkFNRSwgbmFtZSk7CgkJfQoJCXNlcnZlclN0YXRlID0gKChTZXJ2ZXJUeXBlKXNlcnZlclR5cGUpLmdldEluaXRpYWxTdGF0ZSgpOwoJfQoJCglwdWJsaWMgSVNlcnZlclR5cGUgZ2V0U2VydmVyVHlwZSgpIHsKCQlyZXR1cm4gc2VydmVyVHlwZTsKCX0KCQoJcHVibGljIElTZXJ2ZXJXb3JraW5nQ29weSBjcmVhdGVXb3JraW5nQ29weSgpIHsKCQlyZXR1cm4gbmV3IFNlcnZlcldvcmtpbmdDb3B5KHRoaXMpOyAKCX0KCglwdWJsaWMgYm9vbGVhbiBpc1dvcmtpbmdDb3B5KCkgewoJCXJldHVybiBmYWxzZTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgZGVsZXRlRnJvbU1ldGFkYXRhKCkgewoJCVJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpLnJlbW92ZVNlcnZlcih0aGlzKTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgc2F2ZVRvTWV0YWRhdGEoSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJc3VwZXIuc2F2ZVRvTWV0YWRhdGEobW9uaXRvcik7CgkJUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCkuYWRkU2VydmVyKHRoaXMpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgY29tLmlibS53dHAuc2VydmVyLmNvcmUuSVNlcnZlcjIjZ2V0UnVudGltZSgpCgkgKi8KCXB1YmxpYyBJUnVudGltZSBnZXRSdW50aW1lKCkgewoJCXJldHVybiBydW50aW1lOwoJfQoKCXByb3RlY3RlZCBTdHJpbmcgZ2V0UnVudGltZUlkKCkgewoJCXJldHVybiBnZXRBdHRyaWJ1dGUoUlVOVElNRV9JRCwgKFN0cmluZykgbnVsbCk7Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBjb20uaWJtLnd0cC5zZXJ2ZXIuY29yZS5JU2VydmVyMiNnZXRTZXJ2ZXJDb25maWd1cmF0aW9uKCkKCSAqLwoJcHVibGljIElGb2xkZXIgZ2V0U2VydmVyQ29uZmlndXJhdGlvbigpIHsKCQlyZXR1cm4gY29uZmlndXJhdGlvbjsKCX0KCglwcm90ZWN0ZWQgU2VydmVyRGVsZWdhdGUgZ2V0RGVsZWdhdGUoSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKGRlbGVnYXRlICE9IG51bGwpCgkJCXJldHVybiBkZWxlZ2F0ZTsKCQkKCQlpZiAoc2VydmVyVHlwZSAhPSBudWxsKSB7CgkJCXN5bmNocm9uaXplZCAodGhpcykgewoJCQkJaWYgKGRlbGVnYXRlID09IG51bGwpIHsKCQkJCQlKb2Igam9iID0gbmV3IEpvYigiTG9hZCBkZWxlZ2F0ZSIpIHsKCQkJCQkJcHJvdGVjdGVkIElTdGF0dXMgcnVuKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcjIpIHsKCQkJCQkJCXRyeSB7CgkJCQkJCQkJbG9uZyB0aW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJCQkJSUNvbmZpZ3VyYXRpb25FbGVtZW50IGVsZW1lbnQgPSAoKFNlcnZlclR5cGUpIHNlcnZlclR5cGUpLmdldEVsZW1lbnQoKTsKCQkJCQkJCQlkZWxlZ2F0ZSA9IChTZXJ2ZXJEZWxlZ2F0ZSkgZWxlbWVudC5jcmVhdGVFeGVjdXRhYmxlRXh0ZW5zaW9uKCJjbGFzcyIpOwoJCQkJCQkJCUludGVybmFsSW5pdGlhbGl6ZXIuaW5pdGlhbGl6ZVNlcnZlckRlbGVnYXRlKGRlbGVnYXRlLCBTZXJ2ZXIudGhpcyk7CgkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuUEVSRk9STUFOQ0UsICJTZXJ2ZXIuZ2V0RGVsZWdhdGUoKTogPCIgKyAoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCkgLSB0aW1lKSArICI+ICIgKyBnZXRTZXJ2ZXJUeXBlKCkuZ2V0SWQoKSk7CgkJCQkJCQl9IGNhdGNoIChUaHJvd2FibGUgdCkgewoJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkNvdWxkIG5vdCBjcmVhdGUgZGVsZWdhdGUgIiArIHRvU3RyaW5nKCksIHQpOwoJCQkJCQkJfQoJCQkJCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgIiIsIG51bGwpOwoJCQkJCQl9CgkJCQkJfTsKCQkJCQlqb2Iuc2NoZWR1bGUoKTsKCQkJCQl0cnkgewoJCQkJCQlqb2Iuam9pbigpOwoJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCS8vIGlnbm9yZQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gZGVsZWdhdGU7Cgl9CgoJcHJvdGVjdGVkIFNlcnZlckJlaGF2aW91ckRlbGVnYXRlIGdldEJlaGF2aW91ckRlbGVnYXRlKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCWlmIChiZWhhdmlvdXJEZWxlZ2F0ZSAhPSBudWxsKQoJCQlyZXR1cm4gYmVoYXZpb3VyRGVsZWdhdGU7CgkJCgkJaWYgKHNlcnZlclR5cGUgIT0gbnVsbCkgewoJCQlzeW5jaHJvbml6ZWQgKHRoaXMpIHsKCQkJCWlmIChiZWhhdmlvdXJEZWxlZ2F0ZSA9PSBudWxsKSB7CgkJCQkJSm9iIGpvYiA9IG5ldyBKb2IoIkxvYWQgZGVsZWdhdGUiKSB7CgkJCQkJCXByb3RlY3RlZCBJU3RhdHVzIHJ1bihJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IyKSB7CgkJCQkJCQl0cnkgewoJCQkJCQkJCWxvbmcgdGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCQkJCUlDb25maWd1cmF0aW9uRWxlbWVudCBlbGVtZW50ID0gKChTZXJ2ZXJUeXBlKSBzZXJ2ZXJUeXBlKS5nZXRFbGVtZW50KCk7CgkJCQkJCQkJYmVoYXZpb3VyRGVsZWdhdGUgPSAoU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUpIGVsZW1lbnQuY3JlYXRlRXhlY3V0YWJsZUV4dGVuc2lvbigiYmVoYXZpb3VyQ2xhc3MiKTsKCQkJCQkJCQkvL2JlaGF2aW91ckRlbGVnYXRlLmluaXRpYWxpemUoU2VydmVyLnRoaXMpOwoJCQkJCQkJCUludGVybmFsSW5pdGlhbGl6ZXIuaW5pdGlhbGl6ZVNlcnZlckJlaGF2aW91ckRlbGVnYXRlKGJlaGF2aW91ckRlbGVnYXRlLCBTZXJ2ZXIudGhpcyk7CgkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuUEVSRk9STUFOQ0UsICJTZXJ2ZXIuZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKTogPCIgKyAoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCkgLSB0aW1lKSArICI+ICIgKyBnZXRTZXJ2ZXJUeXBlKCkuZ2V0SWQoKSk7CgkJCQkJCQl9IGNhdGNoIChUaHJvd2FibGUgdCkgewoJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkNvdWxkIG5vdCBjcmVhdGUgYmVoYXZpb3VyIGRlbGVnYXRlICIgKyB0b1N0cmluZygpLCB0KTsKCQkJCQkJCX0KCQkJCQkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsICIiLCBudWxsKTsKCQkJCQkJfQoJCQkJCX07CgkJCQkJam9iLnNjaGVkdWxlKCk7CgkJCQkJdHJ5IHsKCQkJCQkJam9iLmpvaW4oKTsKCQkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCQkvLyBpZ25vcmUKCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkJcmV0dXJuIGJlaGF2aW91ckRlbGVnYXRlOwoJfQoKCXB1YmxpYyB2b2lkIGRpc3Bvc2UoKSB7CgkJaWYgKGRlbGVnYXRlICE9IG51bGwpIHsKCQkJZGVsZWdhdGUuZGlzcG9zZSgpOwoJCQlkZWxlZ2F0ZSA9IG51bGw7CgkJfQoJCWlmIChiZWhhdmlvdXJEZWxlZ2F0ZSAhPSBudWxsKSB7CgkJCWJlaGF2aW91ckRlbGVnYXRlLmRpc3Bvc2UoKTsKCQkJYmVoYXZpb3VyRGVsZWdhdGUgPSBudWxsOwoJCX0KCX0KCglwdWJsaWMgU3RyaW5nIGdldEhvc3QoKSB7CgkJcmV0dXJuIGdldEF0dHJpYnV0ZShQUk9QX0hPU1ROQU1FLCAibG9jYWxob3N0Iik7Cgl9CgoJcHVibGljIGludCBnZXRBdXRvUHVibGlzaFRpbWUoKSB7CgkJcmV0dXJuIGdldEF0dHJpYnV0ZShQUk9QX0FVVE9fUFVCTElTSF9USU1FLCAtMSk7Cgl9CgkKCXB1YmxpYyBib29sZWFuIGdldEF1dG9QdWJsaXNoRGVmYXVsdCgpIHsKCQlyZXR1cm4gZ2V0QXR0cmlidXRlKFBST1BfQVVUT19QVUJMSVNIX0RFRkFVTFQsIHRydWUpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgc2VydmVyLiAoc2VlIFNFUlZFUl9YWFggY29uc3RhbnRzKQoJICoKCSAqIEByZXR1cm4gaW50CgkgKi8KCXB1YmxpYyBpbnQgZ2V0U2VydmVyU3RhdGUoKSB7CgkJcmV0dXJuIHNlcnZlclN0YXRlOwoJfQoJCglwdWJsaWMgU3RyaW5nIGdldE1vZGUoKSB7CgkJcmV0dXJuIG1vZGU7Cgl9CgoJcHVibGljIHZvaWQgc2V0U2VydmVyU3RhdGUoaW50IHN0YXRlKSB7CgkJaWYgKHN0YXRlID09IHNlcnZlclN0YXRlKQoJCQlyZXR1cm47CgoJCXRoaXMuc2VydmVyU3RhdGUgPSBzdGF0ZTsKCQlmaXJlU2VydmVyU3RhdGVDaGFuZ2VFdmVudCgpOwoJfQoJCgkvKioKCSAqIEFkZCBhIGxpc3RlbmVyIHRvIHRoaXMgc2VydmVyLgoJICoKCSAqIEBwYXJhbSBsaXN0ZW5lciBvcmcuZWNsaXBzZS53c3Quc2VydmVyLm1vZGVsLklTZXJ2ZXJMaXN0ZW5lcgoJICovCglwdWJsaWMgdm9pZCBhZGRTZXJ2ZXJMaXN0ZW5lcihJU2VydmVyTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlpZiAobGlzdGVuZXIgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTW9kdWxlIGNhbm5vdCBiZSBudWxsIik7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiQWRkaW5nIHNlcnZlciBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIHRvICIgKyB0aGlzKTsKCQlnZXRTZXJ2ZXJOb3RpZmljYXRpb25NYW5hZ2VyKCkuYWRkTGlzdGVuZXIobGlzdGVuZXIpOwoJfQoJCgkvKioKCSAqIEFkZCBhIGxpc3RlbmVyIHRvIHRoaXMgc2VydmVyIHdpdGggdGhlIGdpdmVuIGV2ZW50IG1hc2suCgkgKgoJICogQHBhcmFtIGxpc3RlbmVyIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIubW9kZWwuSVNlcnZlckxpc3RlbmVyCgkgKiBAcGFyYW0gZXZlbnRNYXNrIHRvIGxpbWl0IGxpc3RlbmluZyB0byBjZXJ0YWluIHR5cGVzIG9mIGV2ZW50cwoJICovCglwdWJsaWMgdm9pZCBhZGRTZXJ2ZXJMaXN0ZW5lcihJU2VydmVyTGlzdGVuZXIgbGlzdGVuZXIsIGludCBldmVudE1hc2spIHsKCQlpZiAobGlzdGVuZXIgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTW9kdWxlIGNhbm5vdCBiZSBudWxsIik7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiQWRkaW5nIHNlcnZlciBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIHRvICIgKyB0aGlzICsgIiB3aXRoIGV2ZW50TWFzayAiICsgZXZlbnRNYXNrKTsKCQlnZXRTZXJ2ZXJOb3RpZmljYXRpb25NYW5hZ2VyKCkuYWRkTGlzdGVuZXIobGlzdGVuZXIsIGV2ZW50TWFzayk7Cgl9CgoJLyoqCgkgKiBSZW1vdmUgYSBsaXN0ZW5lciBmcm9tIHRoaXMgc2VydmVyLgoJICoKCSAqIEBwYXJhbSBsaXN0ZW5lciBvcmcuZWNsaXBzZS53c3Quc2VydmVyLm1vZGVsLklTZXJ2ZXJMaXN0ZW5lcgoJICovCglwdWJsaWMgdm9pZCByZW1vdmVTZXJ2ZXJMaXN0ZW5lcihJU2VydmVyTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlpZiAobGlzdGVuZXIgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTW9kdWxlIGNhbm5vdCBiZSBudWxsIik7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiUmVtb3Zpbmcgc2VydmVyIGxpc3RlbmVyICIgKyBsaXN0ZW5lciArICIgZnJvbSAiICsgdGhpcyk7CgkJZ2V0U2VydmVyTm90aWZpY2F0aW9uTWFuYWdlcigpLnJlbW92ZUxpc3RlbmVyKGxpc3RlbmVyKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIHJlc3RhcnQgc3RhdGUgY2hhbmdlIGV2ZW50LgoJICovCglwcm90ZWN0ZWQgdm9pZCBmaXJlUmVzdGFydFN0YXRlQ2hhbmdlRXZlbnQoKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiLT4tIEZpcmluZyBzZXJ2ZXIgcmVzdGFydCBjaGFuZ2UgZXZlbnQ6ICIgKyBnZXROYW1lKCkgKyAiIC0+LSIpOwoJCgkJaWYgKG5vdGlmaWNhdGlvbk1hbmFnZXIgPT0gbnVsbCB8fCBub3RpZmljYXRpb25NYW5hZ2VyLmhhc0xpc3RlbmVyRW50cmllcygpKQoJCQlyZXR1cm47CgkKCQlub3RpZmljYXRpb25NYW5hZ2VyLmJyb2FkY2FzdENoYW5nZSgKCQkJbmV3IFNlcnZlckV2ZW50KFNlcnZlckV2ZW50LlNFUlZFUl9DSEFOR0UgfCBTZXJ2ZXJFdmVudC5SRVNUQVJUX1NUQVRFX0NIQU5HRSwgdGhpcywgZ2V0U2VydmVyU3RhdGUoKSwgCgkJCQlnZXRTZXJ2ZXJQdWJsaXNoU3RhdGUoKSwgZ2V0U2VydmVyUmVzdGFydFN0YXRlKCkpKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIHN0YXRlIGNoYW5nZSBldmVudC4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmlyZVNlcnZlclN0YXRlQ2hhbmdlRXZlbnQoKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiLT4tIEZpcmluZyBzZXJ2ZXIgc3RhdGUgY2hhbmdlIGV2ZW50OiAiICsgZ2V0TmFtZSgpICsgIiwgIiArIGdldFNlcnZlclN0YXRlKCkgKyAiIC0+LSIpOwoJCgkJaWYgKG5vdGlmaWNhdGlvbk1hbmFnZXIgPT0gbnVsbCB8fCBub3RpZmljYXRpb25NYW5hZ2VyLmhhc0xpc3RlbmVyRW50cmllcygpKQoJCQlyZXR1cm47CgkKCQlub3RpZmljYXRpb25NYW5hZ2VyLmJyb2FkY2FzdENoYW5nZSgKCQkJbmV3IFNlcnZlckV2ZW50KFNlcnZlckV2ZW50LlNFUlZFUl9DSEFOR0UgfCBTZXJ2ZXJFdmVudC5TVEFURV9DSEFOR0UsIHRoaXMsIGdldFNlcnZlclN0YXRlKCksIAoJCQkJZ2V0U2VydmVyUHVibGlzaFN0YXRlKCksIGdldFNlcnZlclJlc3RhcnRTdGF0ZSgpKSk7Cgl9CgoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIG1vZHVsZSBzdGF0ZSBjaGFuZ2UgZXZlbnQuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpcmVTZXJ2ZXJNb2R1bGVTdGF0ZUNoYW5nZUV2ZW50KElNb2R1bGVbXSBtb2R1bGUpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICItPi0gRmlyaW5nIHNlcnZlciBtb2R1bGUgc3RhdGUgY2hhbmdlIGV2ZW50OiAiICsgZ2V0TmFtZSgpICsgIiwgIiArIGdldFNlcnZlclN0YXRlKCkgKyAiIC0+LSIpOwoJCQoJCWlmIChub3RpZmljYXRpb25NYW5hZ2VyID09IG51bGwgfHwgbm90aWZpY2F0aW9uTWFuYWdlci5oYXNMaXN0ZW5lckVudHJpZXMoKSkKCQkJcmV0dXJuOwoJCgkJbm90aWZpY2F0aW9uTWFuYWdlci5icm9hZGNhc3RDaGFuZ2UoCgkJCW5ldyBTZXJ2ZXJFdmVudChTZXJ2ZXJFdmVudC5NT0RVTEVfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFLCB0aGlzLCBtb2R1bGUsIGdldE1vZHVsZVN0YXRlKG1vZHVsZSksIAoJCQkJZ2V0TW9kdWxlUHVibGlzaFN0YXRlKG1vZHVsZSksIGdldE1vZHVsZVJlc3RhcnRTdGF0ZShtb2R1bGUpKSk7Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kZShTdHJpbmcgbSkgewoJCXRoaXMubW9kZSA9IG07Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kdWxlU3RhdGUoSU1vZHVsZVtdIG1vZHVsZSwgaW50IHN0YXRlKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJNb2R1bGUgY2Fubm90IGJlIG51bGwiKTsKCQlJbnRlZ2VyIGluID0gbmV3IEludGVnZXIoc3RhdGUpOwoJCW1vZHVsZVN0YXRlLnB1dChnZXRLZXkobW9kdWxlKSwgaW4pOwoJCWZpcmVTZXJ2ZXJNb2R1bGVTdGF0ZUNoYW5nZUV2ZW50KG1vZHVsZSk7Cgl9CgkKCXB1YmxpYyB2b2lkIHNldE1vZHVsZVB1Ymxpc2hTdGF0ZShJTW9kdWxlW10gbW9kdWxlLCBpbnQgc3RhdGUpIHsKCQlpZiAobW9kdWxlID09IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oIk1vZHVsZSBjYW5ub3QgYmUgbnVsbCIpOwoJCUludGVnZXIgaW4gPSBuZXcgSW50ZWdlcihzdGF0ZSk7CgkJbW9kdWxlUHVibGlzaFN0YXRlLnB1dChnZXRLZXkobW9kdWxlKSwgaW4pOwoJCS8vZmlyZVNlcnZlck1vZHVsZVN0YXRlQ2hhbmdlRXZlbnQobW9kdWxlKTsKCX0KCglwdWJsaWMgdm9pZCBzZXRNb2R1bGVSZXN0YXJ0U3RhdGUoSU1vZHVsZVtdIG1vZHVsZSwgYm9vbGVhbiByKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJNb2R1bGUgY2Fubm90IGJlIG51bGwiKTsKCQlCb29sZWFuIGIgPSBuZXcgQm9vbGVhbihyKTsKCQltb2R1bGVTdGF0ZS5wdXQoZ2V0S2V5KG1vZHVsZSksIGIpOwoJCS8vZmlyZVNlcnZlck1vZHVsZVN0YXRlQ2hhbmdlRXZlbnQobW9kdWxlKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCBoYW5kbGVNb2R1bGVQcm9qZWN0Q2hhbmdlKGZpbmFsIElNb2R1bGUgbW9kdWxlKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiPiBoYW5kbGVEZXBsb3lhYmxlUHJvamVjdENoYW5nZSgpICIgKyB0aGlzICsgIiAiICsgbW9kdWxlKTsKCQkKCQljbGFzcyBIZWxwZXIgewoJCQlib29sZWFuIGNoYW5nZWQ7CgkJfQoJCWZpbmFsIEhlbHBlciBoZWxwZXIgPSBuZXcgSGVscGVyKCk7CgkJCgkJSU1vZHVsZVZpc2l0b3IgdmlzaXRvciA9IG5ldyBJTW9kdWxlVmlzaXRvcigpIHsKCQkJcHVibGljIGJvb2xlYW4gdmlzaXQoSU1vZHVsZVtdIG1vZHVsZTIpIHsKCQkJCWludCBzaXplID0gbW9kdWxlMi5sZW5ndGg7CgkJCQlJTW9kdWxlIG0gPSBtb2R1bGUyW3NpemUgLSAxXTsKCQkJCWlmIChtLmdldFByb2plY3QoKSA9PSBudWxsKQoJCQkJCXJldHVybiB0cnVlOwoJCQkJCgkJCQlpZiAobW9kdWxlLmVxdWFscyhtKSkgewoJCQkJCUlNb2R1bGVSZXNvdXJjZURlbHRhW10gZGVsdGEyID0gZ2V0UHVibGlzaGVkUmVzb3VyY2VEZWx0YShtb2R1bGUyKTsKCQkJCQlpZiAoZGVsdGEyLmxlbmd0aCA+IDApCgkJCQkJCWhlbHBlci5jaGFuZ2VkID0gdHJ1ZTsKCQkJCQkKCQkJCQkvLyBUT0RPCgkJCQkJLyppZiAoZGVwbG95YWJsZURlbHRhW2ldID09IG51bGwpCgkJCQkJCWRlcGxveWFibGVEZWx0YVtpXSA9IG1vZHVsZVByb2plY3RzW2ldLmdldE1vZHVsZVJlc291cmNlRGVsdGEoZGVsdGEpOwoJCQkJCQoJCQkJCWlmIChkZXBsb3lhYmxlRGVsdGFbaV0gIT0gbnVsbCkgewoJCQkJCQkvLyB1cGRhdGVEZXBsb3lhYmxlKG1vZHVsZSwgZGVwbG95YWJsZURlbHRhW2ldKTsKCgkJCQkJCU1vZHVsZVB1Ymxpc2hJbmZvIGNvbnRyb2wgPSBQdWJsaXNoSW5mby5nZXRQdWJsaXNoSW5mbygpLmdldFB1Ymxpc2hDb250cm9sKFNlcnZlci50aGlzLCBwYXJlbnRzLCBtb2R1bGUpOwoJCQkJCQlpZiAoY29udHJvbC5pc0RpcnR5KCkpCgkJCQkJCQlyZXR1cm4gdHJ1ZTsKCQoJCQkJCQljb250cm9sLnNldERpcnR5KHRydWUpOwoJCQkJCQlmaXJlUHVibGlzaFN0YXRlQ2hhbmdlKHBhcmVudHMsIG1vZHVsZSk7CgkJCQkJfSovCgkJCQkJcmV0dXJuIHRydWU7CgkJCQl9CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX07CgoJCXZpc2l0KHZpc2l0b3IsIG51bGwpOwoJCQoJCWlmICghaGVscGVyLmNoYW5nZWQpCgkJCXJldHVybjsKCQkKCQkvLyBjaGVjayBmb3IgYXV0by1wdWJsaXNoCgkJaWYgKGF1dG9QdWJsaXNoVGhyZWFkICE9IG51bGwpIHsKCQkJYXV0b1B1Ymxpc2hUaHJlYWQuc3RvcCA9IHRydWU7CgkJCWF1dG9QdWJsaXNoVGhyZWFkLmludGVycnVwdCgpOwoJCQlhdXRvUHVibGlzaFRocmVhZCA9IG51bGw7CgkJfQoJCQoJCWludCB0aW1lID0gMDsKCQlpZiAoZ2V0QXV0b1B1Ymxpc2hEZWZhdWx0KCkpIHsKCQkJYm9vbGVhbiBsb2NhbCA9IFNvY2tldFV0aWwuaXNMb2NhbGhvc3QoZ2V0SG9zdCgpKTsKCQkJaWYgKGxvY2FsICYmIFNlcnZlclByZWZlcmVuY2VzLmdldEluc3RhbmNlKCkuZ2V0QXV0b1B1Ymxpc2hMb2NhbCgpKQoJCQkJdGltZSA9IFNlcnZlclByZWZlcmVuY2VzLmdldEluc3RhbmNlKCkuZ2V0QXV0b1B1Ymxpc2hMb2NhbFRpbWUoKTsKCQkJZWxzZSBpZiAoIWxvY2FsICYmIFNlcnZlclByZWZlcmVuY2VzLmdldEluc3RhbmNlKCkuZ2V0QXV0b1B1Ymxpc2hSZW1vdGUoKSkKCQkJCXRpbWUgPSBTZXJ2ZXJQcmVmZXJlbmNlcy5nZXRJbnN0YW5jZSgpLmdldEF1dG9QdWJsaXNoUmVtb3RlVGltZSgpOwoJCX0gZWxzZSB7CgkJCXRpbWUgPSBnZXRBdXRvUHVibGlzaFRpbWUoKTsKCQl9CgkJCgkJaWYgKHRpbWUgPiA1KSB7CgkJCWF1dG9QdWJsaXNoVGhyZWFkID0gbmV3IEF1dG9QdWJsaXNoVGhyZWFkKCk7CgkJCWF1dG9QdWJsaXNoVGhyZWFkLnRpbWUgPSB0aW1lOwoJCQlhdXRvUHVibGlzaFRocmVhZC5zZXRQcmlvcml0eShUaHJlYWQuTUlOX1BSSU9SSVRZICsgMSk7CgkJCWF1dG9QdWJsaXNoVGhyZWFkLnN0YXJ0KCk7CgkJfQoJCQoJCS8vVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiPCBoYW5kbGVEZXBsb3lhYmxlUHJvamVjdENoYW5nZSgpIik7Cgl9CgkKCXByaXZhdGUgU2VydmVyTm90aWZpY2F0aW9uTWFuYWdlciBnZXRTZXJ2ZXJOb3RpZmljYXRpb25NYW5hZ2VyKCkgewoJCWlmIChub3RpZmljYXRpb25NYW5hZ2VyID09IG51bGwpIHsKCQkJbm90aWZpY2F0aW9uTWFuYWdlciA9IG5ldyBTZXJ2ZXJOb3RpZmljYXRpb25NYW5hZ2VyKCk7CgkJfQoJCXJldHVybiBub3RpZmljYXRpb25NYW5hZ2VyOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgY29uZmlndXJhdGlvbidzIHN5bmMgc3RhdGUuCgkgKgoJICogQHJldHVybiBpbnQKCSAqLwoJcHVibGljIGludCBnZXRTZXJ2ZXJQdWJsaXNoU3RhdGUoKSB7CgkJcmV0dXJuIHNlcnZlclN5bmNTdGF0ZTsKCX0KCgkvKioKCSAqIFNldHMgdGhlIGNvbmZpZ3VyYXRpb24gc3luYyBzdGF0ZS4KCSAqCgkgKiBAcGFyYW0gc3RhdGUgaW50CgkgKi8KCXB1YmxpYyB2b2lkIHNldFNlcnZlclB1Ymxpc2hTdGF0ZShpbnQgc3RhdGUpIHsKCQlpZiAoc3RhdGUgPT0gc2VydmVyU3luY1N0YXRlKQoJCQlyZXR1cm47CgkJc2VydmVyU3luY1N0YXRlID0gc3RhdGU7CgkJLy9maXJlQ29uZmlndXJhdGlvblN5bmNTdGF0ZUNoYW5nZUV2ZW50KCk7Cgl9CgoJLyoqCgkgKiBBZGRzIGEgcHVibGlzaCBsaXN0ZW5lciB0byB0aGlzIHNlcnZlci4KCSAqIEhhcyBubyBlZmZlY3QgaWYgYW4gaWRlbnRpY2FsIGxpc3RlbmVyIGlzIGFscmVhZHkgcmVnaXN0ZXJlZC4KCSAqCgkgKiBAcGFyYW0gbGlzdGVuZXIgdGhlIHB1Ymxpc2ggbGlzdGVuZXIKCSAqIEBzZWUgI3JlbW92ZVB1Ymxpc2hMaXN0ZW5lcihJUHVibGlzaExpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCBhZGRQdWJsaXNoTGlzdGVuZXIoSVB1Ymxpc2hMaXN0ZW5lciBsaXN0ZW5lcikgewoJCWlmIChsaXN0ZW5lciA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJMaXN0ZW5lciBjYW5ub3QgYmUgbnVsbCIpOwoJCVRyYWNlLnRyYWNlKFRyYWNlLkxJU1RFTkVSUywgIkFkZGluZyBwdWJsaXNoIGxpc3RlbmVyICIgKyBsaXN0ZW5lciArICIgdG8gIiArIHRoaXMpOwoKCQlpZiAocHVibGlzaExpc3RlbmVycyA9PSBudWxsKQoJCQlwdWJsaXNoTGlzdGVuZXJzID0gbmV3IEFycmF5TGlzdCgpOwoJCXB1Ymxpc2hMaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTsKCX0KCgkvKioKCSAqIFJlbW92ZXMgYSBwdWJsaXNoIGxpc3RlbmVyIGZyb20gdGhpcyBzZXJ2ZXIuCgkgKiBIYXMgbm8gZWZmZWN0IGlmIHRoZSBsaXN0ZW5lciBpcyBub3QgcmVnaXN0ZXJlZC4KCSAqCgkgKiBAcGFyYW0gbGlzdGVuZXIgdGhlIHB1Ymxpc2ggbGlzdGVuZXIKCSAqIEBzZWUgI2FkZFB1Ymxpc2hMaXN0ZW5lcihJUHVibGlzaExpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQdWJsaXNoTGlzdGVuZXIoSVB1Ymxpc2hMaXN0ZW5lciBsaXN0ZW5lcikgewoJCWlmIChsaXN0ZW5lciA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJMaXN0ZW5lciBjYW5ub3QgYmUgbnVsbCIpOwoJCVRyYWNlLnRyYWNlKFRyYWNlLkxJU1RFTkVSUywgIlJlbW92aW5nIHB1Ymxpc2ggbGlzdGVuZXIgIiArIGxpc3RlbmVyICsgIiBmcm9tICIgKyB0aGlzKTsKCgkJaWYgKHB1Ymxpc2hMaXN0ZW5lcnMgIT0gbnVsbCkKCQkJcHVibGlzaExpc3RlbmVycy5yZW1vdmUobGlzdGVuZXIpOwoJfQoJCgkvKioKCSAqIEZpcmUgYSBwdWJsaXNoIHN0YXJ0IGV2ZW50LgoJICovCglwcml2YXRlIHZvaWQgZmlyZVB1Ymxpc2hTdGFydGVkKCkgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0+LSBGaXJpbmcgcHVibGlzaCBzdGFydGVkIGV2ZW50IC0+LSIpOwoJCgkJaWYgKHB1Ymxpc2hMaXN0ZW5lcnMgPT0gbnVsbCB8fCBwdWJsaXNoTGlzdGVuZXJzLmlzRW1wdHkoKSkKCQkJcmV0dXJuOwoKCQlpbnQgc2l6ZSA9IHB1Ymxpc2hMaXN0ZW5lcnMuc2l6ZSgpOwoJCUlQdWJsaXNoTGlzdGVuZXJbXSBzcmwgPSBuZXcgSVB1Ymxpc2hMaXN0ZW5lcltzaXplXTsKCQlwdWJsaXNoTGlzdGVuZXJzLnRvQXJyYXkoc3JsKTsKCgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiICBGaXJpbmcgcHVibGlzaCBzdGFydGVkIGV2ZW50IHRvICIgKyBzcmxbaV0pOwoJCQl0cnkgewoJCQkJc3JsW2ldLnB1Ymxpc2hTdGFydGVkKHRoaXMpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgcHVibGlzaCBzdGFydGVkIGV2ZW50IHRvICIgKyBzcmxbaV0sIGUpOwoJCQl9CgkJfQoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItPC0gRG9uZSBmaXJpbmcgcHVibGlzaCBzdGFydGVkIGV2ZW50IC08LSIpOwoJfQoKCS8qKgoJICogRmlyZSBhIHB1Ymxpc2ggc3RvcCBldmVudC4KCSAqCgkgKiBAcGFyYW0gc3RhdHVzIHB1Ymxpc2hpbmcgc3RhdHVzCgkgKi8KCXByaXZhdGUgdm9pZCBmaXJlUHVibGlzaEZpbmlzaGVkKElTdGF0dXMgc3RhdHVzKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLT4tIEZpcmluZyBwdWJsaXNoaW5nIGZpbmlzaGVkIGV2ZW50OiAiICsgc3RhdHVzICsgIiAtPi0iKTsKCQoJCWlmIChwdWJsaXNoTGlzdGVuZXJzID09IG51bGwgfHwgcHVibGlzaExpc3RlbmVycy5pc0VtcHR5KCkpCgkJCXJldHVybjsKCgkJaW50IHNpemUgPSBwdWJsaXNoTGlzdGVuZXJzLnNpemUoKTsKCQlJUHVibGlzaExpc3RlbmVyW10gc3JsID0gbmV3IElQdWJsaXNoTGlzdGVuZXJbc2l6ZV07CgkJcHVibGlzaExpc3RlbmVycy50b0FycmF5KHNybCk7CgoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIiAgRmlyaW5nIHB1Ymxpc2hpbmcgZmluaXNoZWQgZXZlbnQgdG8gIiArIHNybFtpXSk7CgkJCXRyeSB7CgkJCQlzcmxbaV0ucHVibGlzaEZpbmlzaGVkKHRoaXMsIHN0YXR1cyk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICIgIEVycm9yIGZpcmluZyBwdWJsaXNoaW5nIGZpbmlzaGVkIGV2ZW50IHRvICIgKyBzcmxbaV0sIGUpOwoJCQl9CgkJfQoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItPC0gRG9uZSBmaXJpbmcgcHVibGlzaGluZyBmaW5pc2hlZCBldmVudCAtPC0iKTsKCX0KCgkvKioKCSAqIEZpcmUgYSBwdWJsaXNoIHN0YXRlIGNoYW5nZSBldmVudC4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmlyZVB1Ymxpc2hTdGF0ZUNoYW5nZShJTW9kdWxlW10gbW9kdWxlKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLT4tIEZpcmluZyBwdWJsaXNoIHN0YXRlIGNoYW5nZSBldmVudDogIiArIG1vZHVsZSArICIgLT4tIik7CgkKCQlpZiAobm90aWZpY2F0aW9uTWFuYWdlciA9PSBudWxsIHx8IG5vdGlmaWNhdGlvbk1hbmFnZXIuaGFzTGlzdGVuZXJFbnRyaWVzKCkpCgkJCXJldHVybjsKCQoJCW5vdGlmaWNhdGlvbk1hbmFnZXIuYnJvYWRjYXN0Q2hhbmdlKAoJCQluZXcgU2VydmVyRXZlbnQoU2VydmVyRXZlbnQuTU9EVUxFX0NIQU5HRSB8IFNlcnZlckV2ZW50LlBVQkxJU0hfU1RBVEVfQ0hBTkdFLCB0aGlzLCBtb2R1bGUsIGdldE1vZHVsZVN0YXRlKG1vZHVsZSksIAoJCQkJZ2V0TW9kdWxlUHVibGlzaFN0YXRlKG1vZHVsZSksIGdldE1vZHVsZVJlc3RhcnRTdGF0ZShtb2R1bGUpKSk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNlcnZlciBpcyBpbiBhIHN0YXRlIHRoYXQgaXQgY2FuCgkgKiBiZSBwdWJsaXNoZWQgdG8uCgkgKgoJICogQHJldHVybiBib29sZWFuCgkgKi8KCXB1YmxpYyBJU3RhdHVzIGNhblB1Ymxpc2goKSB7CgkJLy8gY2FuJ3QgcHVibGlzaCBpZiB0aGUgc2VydmVyIGlzIHN0YXJ0aW5nIG9yIHN0b3BwaW5nCgkJaW50IHN0YXRlID0gZ2V0U2VydmVyU3RhdGUoKTsKCQlpZiAoc3RhdGUgPT0gU1RBVEVfU1RBUlRJTkcgfHwgc3RhdGUgPT0gU1RBVEVfU1RPUFBJTkcpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yUHVibGlzaFN0YXJ0aW5nLCBudWxsKTsKCQoJCS8vIGNhbid0IHB1Ymxpc2ggaWYgdGhlcmUgaXMgbm8gY29uZmlndXJhdGlvbgoJCWlmIChnZXRTZXJ2ZXJUeXBlKCkgPT0gbnVsbCB8fCBnZXRTZXJ2ZXJUeXBlKCkuaGFzU2VydmVyQ29uZmlndXJhdGlvbigpICYmIGNvbmZpZ3VyYXRpb24gPT0gbnVsbCkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMuZXJyb3JQdWJsaXNoTm9Db25maWd1cmF0aW9uLCBudWxsKTsKCQoJCS8vIHJldHVybiB0cnVlIGlmIHRoZSBjb25maWd1cmF0aW9uIGNhbiBiZSBwdWJsaXNoZWQKCQlpZiAoZ2V0U2VydmVyUHVibGlzaFN0YXRlKCkgIT0gUFVCTElTSF9TVEFURV9OT05FKQoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5jYW5QdWJsaXNoT2ssIG51bGwpOwoKCQkvLyByZXR1cm4gdHJ1ZSBpZiBhbnkgbW9kdWxlcyBjYW4gYmUgcHVibGlzaGVkCgkJY2xhc3MgVGVtcCB7CgkJCWJvb2xlYW4gZm91bmQgPSBmYWxzZTsKCQl9CgkJLy9maW5hbCBUZW1wIHRlbXAgPSBuZXcgVGVtcCgpOwoJCQoJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmNhblB1Ymxpc2hPaywgbnVsbCk7CgkKCQkvKklNb2R1bGVWaXNpdG9yIHZpc2l0b3IgPSBuZXcgSU1vZHVsZVZpc2l0b3IoKSB7CgkJCXB1YmxpYyBib29sZWFuIHZpc2l0KElNb2R1bGVbXSBwYXJlbnRzLCBJTW9kdWxlIG1vZHVsZSkgewoJCQkJaWYgKGdldE1vZHVsZVB1Ymxpc2hTdGF0ZShtb2R1bGUpICE9IFBVQkxJU0hfU1RBVEVfTk9ORSkgewoJCQkJCXRlbXAuZm91bmQgPSB0cnVlOwoJCQkJCXJldHVybiBmYWxzZTsKCQkJCX0KCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJfTsKCQlTZXJ2ZXJVdGlsLnZpc2l0KHRoaXMsIHZpc2l0b3IsIG51bGwpOwoJCQoJCXJldHVybiB0ZW1wLmZvdW5kOyovCgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNlcnZlciBpcyBpbiBhIHN0YXRlIHRoYXQgaXQgY2FuCgkgKiBiZSBwdWJsaXNoZWQgdG8uCgkgKgoJICogQHJldHVybiBib29sZWFuCgkgKi8KCXB1YmxpYyBib29sZWFuIHNob3VsZFB1Ymxpc2goKSB7CgkJaWYgKCFjYW5QdWJsaXNoKCkuaXNPSygpKQoJCQlyZXR1cm4gZmFsc2U7CgkKCQlpZiAoZ2V0U2VydmVyUHVibGlzaFN0YXRlKCkgIT0gUFVCTElTSF9TVEFURV9OT05FKQoJCQlyZXR1cm4gdHJ1ZTsKCQoJCS8vaWYgKGdldFVucHVibGlzaGVkTW9kdWxlcygpLmxlbmd0aCA+IDApCgkJcmV0dXJuIHRydWU7CgkKCQkvL3JldHVybiBmYWxzZTsKCX0KCglwdWJsaWMgU2VydmVyUHVibGlzaEluZm8gZ2V0U2VydmVyUHVibGlzaEluZm8oKSB7CgkJaWYgKHB1Ymxpc2hJbmZvID09IG51bGwpIHsKCQkJcHVibGlzaEluZm8gPSBQdWJsaXNoSW5mby5nZXRJbnN0YW5jZSgpLmdldFNlcnZlclB1Ymxpc2hJbmZvKHRoaXMpOwoJCX0KCQlyZXR1cm4gcHVibGlzaEluZm87Cgl9CgoJLyoKCSAqIFB1Ymxpc2ggdG8gdGhlIHNlcnZlciB1c2luZyB0aGUgcHJvZ3Jlc3MgbW9uaXRvci4gVGhlIHJlc3VsdCBvZiB0aGUKCSAqIHB1Ymxpc2ggb3BlcmF0aW9uIGlzIHJldHVybmVkIGFzIGFuIElTdGF0dXMuCgkgKi8KCXB1YmxpYyBJU3RhdHVzIHB1Ymxpc2goZmluYWwgaW50IGtpbmQsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCWlmIChnZXRTZXJ2ZXJUeXBlKCkgPT0gbnVsbCkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMuZXJyb3JQdWJsaXNoaW5nLCBudWxsKTsKCgkJLy8gY2hlY2sgd2hhdCBpcyBvdXQgb2Ygc3luYyBhbmQgcHVibGlzaAoJCWlmIChnZXRTZXJ2ZXJUeXBlKCkuaGFzU2VydmVyQ29uZmlndXJhdGlvbigpICYmIGNvbmZpZ3VyYXRpb24gPT0gbnVsbCkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMuZXJyb3JOb0NvbmZpZ3VyYXRpb24sIG51bGwpOwoJCQoJCWlmICgoKFNlcnZlclR5cGUpZ2V0U2VydmVyVHlwZSgpKS5zdGFydEJlZm9yZVB1Ymxpc2goKSkgewoJCQl0cnkgewoJCQkJc3luY2hyb25vdXNTdGFydChJTGF1bmNoTWFuYWdlci5SVU5fTU9ERSwgbW9uaXRvcik7CgkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHN0YXJ0aW5nIHNlcnZlciIsIGNlKTsKCQkJCXJldHVybiBjZS5nZXRTdGF0dXMoKTsKCQkJfQoJCX0KCQkKCQlJU3RhdHVzIHN0YXR1cyA9IG51bGw7CgkJdHJ5IHsKCQkJZmlyZVB1Ymxpc2hTdGFydGVkKCk7CgkJCXN0YXR1cyA9IGRvUHVibGlzaChraW5kLCBtb25pdG9yKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlzdGF0dXMgPSBudWxsOyAvLyBUT0RPCgkJfSBmaW5hbGx5IHsKCQkJZmlyZVB1Ymxpc2hGaW5pc2hlZChzdGF0dXMpOwoJCX0KCQlyZXR1cm4gc3RhdHVzOwoJfQoKCXByb3RlY3RlZCBJU3RhdHVzIGRvUHVibGlzaChpbnQga2luZCwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLS0+LS0gUHVibGlzaGluZyB0byBzZXJ2ZXI6ICIgKyB0b1N0cmluZygpICsgIiAtLT4tLSIpOwoKCQl0cnkgewoJCQlyZXR1cm4gZ2V0QmVoYXZpb3VyRGVsZWdhdGUobW9uaXRvcikucHVibGlzaChraW5kLCBtb25pdG9yKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIHB1Ymxpc2goKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXJldHVybiBudWxsOwoJCX0KCX0KCQoJLyoqCgkgKiBSZXR1cm5zIHRoZSBwdWJsaXNoIHRhc2tzIHRoYXQgaGF2ZSBiZWVuIHRhcmdldHRlZCB0byB0aGlzIHNlcnZlci4KCSAqIFRoZXNlIHRhc2tzIHNob3VsZCBiZSBydW4gZHVyaW5nIHB1Ymxpc2hpbmcuCgkgKiAKCSAqIEByZXR1cm4gYSBwb3NzaWJseSBlbXB0eSBhcnJheSBvZiBJT3B0aW9uYWxUYXNrcwoJICovCglwdWJsaWMgUHVibGlzaE9wZXJhdGlvbltdIGdldFRhc2tzKCkgewoJCWZpbmFsIExpc3QgbW9kdWxlTGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCQkKCQlJTW9kdWxlVmlzaXRvciB2aXNpdG9yID0gbmV3IElNb2R1bGVWaXNpdG9yKCkgewoJCQlwdWJsaWMgYm9vbGVhbiB2aXNpdChJTW9kdWxlW10gbW9kdWxlKSB7CgkJCQltb2R1bGVMaXN0LmFkZChtb2R1bGUpOwoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9OwoKCQl2aXNpdCh2aXNpdG9yLCBudWxsKTsKCQoJCUxpc3QgdGFza3MgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCgkJU3RyaW5nIHNlcnZlclR5cGVJZCA9IGdldFNlcnZlclR5cGUoKS5nZXRJZCgpOwoJCQoJCUlQdWJsaXNoVGFza1tdIHB1Ymxpc2hUYXNrcyA9IFNlcnZlclBsdWdpbi5nZXRQdWJsaXNoVGFza3MoKTsKCQlpZiAocHVibGlzaFRhc2tzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBwdWJsaXNoVGFza3MubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJSVB1Ymxpc2hUYXNrIHRhc2sgPSBwdWJsaXNoVGFza3NbaV07CgkJCQlpZiAodGFzay5zdXBwb3J0c1R5cGUoc2VydmVyVHlwZUlkKSkgewoJCQkJCVB1Ymxpc2hPcGVyYXRpb25bXSB0YXNrczIgPSB0YXNrLmdldFRhc2tzKHRoaXMsIG1vZHVsZUxpc3QpOwoJCQkJCWlmICh0YXNrczIgIT0gbnVsbCkgewoJCQkJCQlpbnQgc2l6ZTIgPSB0YXNrczIubGVuZ3RoOwoJCQkJCQlmb3IgKGludCBqID0gMDsgaiA8IHNpemUyOyBqKyspIHsKCQkJCQkJCWlmICh0YXNrczJbal0uZ2V0S2luZCgpID09IFB1Ymxpc2hPcGVyYXRpb24uUkVRVUlSRUQpCgkJCQkJCQkJdGFza3MuYWRkKHRhc2tzMltqXSk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkJCgkJcmV0dXJuIChQdWJsaXNoT3BlcmF0aW9uW10pIHRhc2tzLnRvQXJyYXkobmV3IFB1Ymxpc2hPcGVyYXRpb25bdGFza3Muc2l6ZSgpXSk7Cgl9CgkKCXB1YmxpYyBMaXN0IGdldEFsbE1vZHVsZXMoKSB7CgkJZmluYWwgTGlzdCBtb2R1bGVMaXN0ID0gbmV3IEFycmF5TGlzdCgpOwoJCQoJCUlNb2R1bGVWaXNpdG9yIHZpc2l0b3IgPSBuZXcgSU1vZHVsZVZpc2l0b3IoKSB7CgkJCXB1YmxpYyBib29sZWFuIHZpc2l0KElNb2R1bGVbXSBtb2R1bGUpIHsKCQkJCW1vZHVsZUxpc3QuYWRkKG1vZHVsZSk7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX07CgoJCXZpc2l0KHZpc2l0b3IsIG51bGwpOwoJCQoJCXJldHVybiBtb2R1bGVMaXN0OwoJfQoKCS8qCgkgKiBSZXR1cm5zIHRoZSBtb2R1bGUgcmVzb3VyY2VzIHRoYXQgaGF2ZSBiZWVuIHB1Ymxpc2hlZC4KCSAqIAoJICogQHNlZSBTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZS5nZXRQdWJsaXNoZWRSZXNvdXJjZXMoSU1vZHVsZVtdLCBJTW9kdWxlKQoJICovCglwdWJsaWMgSU1vZHVsZVJlc291cmNlW10gZ2V0UHVibGlzaGVkUmVzb3VyY2VzKElNb2R1bGVbXSBtb2R1bGUpIHsKCQlpZiAobW9kdWxlID09IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oIk1vZHVsZSBjYW5ub3QgYmUgbnVsbCIpOwoJCXJldHVybiBnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpLmdldE1vZHVsZVB1Ymxpc2hJbmZvKG1vZHVsZSkuZ2V0UmVzb3VyY2VzKCk7Cgl9CgoJLyoKCSAqIFJldHVybnMgdGhlIGRlbHRhIG9mIHRoZSBjdXJyZW50IG1vZHVsZSByZXNvdXJjZXMgdGhhdCBoYXZlIGJlZW4KCSAqIHB1Ymxpc2hlZCBjb21wYXJlZCB0byB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgbW9kdWxlLgoJICogCgkgKiBAc2VlIFNlcnZlckJlaGF2aW91ckRlbGVnYXRlLmdldFB1Ymxpc2hlZFJlc291cmNlRGVsdGEoSU1vZHVsZVtdLCBJTW9kdWxlKQoJICovCglwdWJsaWMgSU1vZHVsZVJlc291cmNlRGVsdGFbXSBnZXRQdWJsaXNoZWRSZXNvdXJjZURlbHRhKElNb2R1bGVbXSBtb2R1bGUpIHsKCQlpZiAobW9kdWxlID09IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oIk1vZHVsZSBjYW5ub3QgYmUgbnVsbCIpOwoJCXJldHVybiBnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpLmdldERlbHRhKG1vZHVsZSk7Cgl9CgoJLyoqCgkgKiBAc2VlIElTZXJ2ZXIjZ2V0QWRhcHRlcihDbGFzcykKCSAqLwoJcHVibGljIE9iamVjdCBnZXRBZGFwdGVyKENsYXNzIGFkYXB0ZXIpIHsKCQlpZiAoZGVsZWdhdGUgIT0gbnVsbCkgewoJCQlpZiAoYWRhcHRlci5pc0luc3RhbmNlKGRlbGVnYXRlKSkKCQkJCXJldHVybiBkZWxlZ2F0ZTsKCQl9CgkJaWYgKGJlaGF2aW91ckRlbGVnYXRlICE9IG51bGwpIHsKCQkJaWYgKGFkYXB0ZXIuaXNJbnN0YW5jZShiZWhhdmlvdXJEZWxlZ2F0ZSkpCgkJCQlyZXR1cm4gYmVoYXZpb3VyRGVsZWdhdGU7CgkJfQoJCXJldHVybiBQbGF0Zm9ybS5nZXRBZGFwdGVyTWFuYWdlcigpLmdldEFkYXB0ZXIodGhpcywgYWRhcHRlcik7Cgl9CgoJLyoqCgkgKiBAc2VlIElTZXJ2ZXIjbG9hZEFkYXB0ZXIoQ2xhc3MsIElQcm9ncmVzc01vbml0b3IpCgkgKi8KCXB1YmxpYyBPYmplY3QgbG9hZEFkYXB0ZXIoQ2xhc3MgYWRhcHRlciwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJZ2V0RGVsZWdhdGUobW9uaXRvcik7CgkJaWYgKGFkYXB0ZXIuaXNJbnN0YW5jZShkZWxlZ2F0ZSkpCgkJCXJldHVybiBkZWxlZ2F0ZTsKCgkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUobW9uaXRvcik7CgkJaWYgKGFkYXB0ZXIuaXNJbnN0YW5jZShiZWhhdmlvdXJEZWxlZ2F0ZSkpCgkJCXJldHVybiBiZWhhdmlvdXJEZWxlZ2F0ZTsKCQkKCQlyZXR1cm4gUGxhdGZvcm0uZ2V0QWRhcHRlck1hbmFnZXIoKS5sb2FkQWRhcHRlcih0aGlzLCBhZGFwdGVyLmdldE5hbWUoKSk7Cgl9CgoJcHVibGljIFN0cmluZyB0b1N0cmluZygpIHsKCQlyZXR1cm4gZ2V0TmFtZSgpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIHRoZSBzZXJ2ZXIgaXMgaW4gYSBzdGF0ZSB0aGF0IGl0IGNhbgoJICogYmUgc3RhcnRlZCwgYW5kIHN1cHBvcnRzIHRoZSBnaXZlbiBtb2RlLgoJICoKCSAqIEBwYXJhbSBtb2RlMgoJICogQHJldHVybiBzdGF0dXMKCSAqLwoJcHVibGljIElTdGF0dXMgY2FuU3RhcnQoU3RyaW5nIG1vZGUyKSB7CgkJaW50IHN0YXRlID0gZ2V0U2VydmVyU3RhdGUoKTsKCQlpZiAoc3RhdGUgIT0gU1RBVEVfU1RPUFBFRCAmJiBzdGF0ZSAhPSBTVEFURV9VTktOT1dOKQoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5jYW5TdGFydEVycm9yU3RhdGUsIG51bGwpOwoJCQoJCWlmIChnZXRTZXJ2ZXJUeXBlKCkgPT0gbnVsbCB8fCAhZ2V0U2VydmVyVHlwZSgpLnN1cHBvcnRzTGF1bmNoTW9kZShtb2RlMikpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yTGF1bmNoTW9kZSwgbnVsbCk7CgoJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmNhblN0YXJ0T2ssIG51bGwpOwoJfQoJCglwdWJsaWMgSUxhdW5jaCBnZXRFeGlzdGluZ0xhdW5jaCgpIHsKCQlJTGF1bmNoTWFuYWdlciBsYXVuY2hNYW5hZ2VyID0gRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldExhdW5jaE1hbmFnZXIoKTsKCQkKCQlJTGF1bmNoW10gbGF1bmNoZXMgPSBsYXVuY2hNYW5hZ2VyLmdldExhdW5jaGVzKCk7CgkJaW50IHNpemUgPSBsYXVuY2hlcy5sZW5ndGg7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJSUxhdW5jaENvbmZpZ3VyYXRpb24gbGF1bmNoQ29uZmlnID0gbGF1bmNoZXNbaV0uZ2V0TGF1bmNoQ29uZmlndXJhdGlvbigpOwoJCQl0cnkgewoJCQkJaWYgKGxhdW5jaENvbmZpZyAhPSBudWxsKSB7CgkJCQkJU3RyaW5nIHNlcnZlcklkID0gbGF1bmNoQ29uZmlnLmdldEF0dHJpYnV0ZShTRVJWRVJfSUQsIChTdHJpbmcpIG51bGwpOwoJCQkJCWlmIChnZXRJZCgpLmVxdWFscyhzZXJ2ZXJJZCkpIHsKCQkJCQkJaWYgKCFsYXVuY2hlc1tpXS5pc1Rlcm1pbmF0ZWQoKSkKCQkJCQkJCXJldHVybiBsYXVuY2hlc1tpXTsKCQkJCQl9CgkJCQl9CgkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkJLy8gaWdub3JlCgkJCX0KCQl9CgkJCgkJcmV0dXJuIG51bGw7Cgl9CgoJcHVibGljIHZvaWQgc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKElMYXVuY2hDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgd29ya2luZ0NvcHksIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCXRyeSB7CgkJCWdldEJlaGF2aW91ckRlbGVnYXRlKG1vbml0b3IpLnNldHVwTGF1bmNoQ29uZmlndXJhdGlvbih3b3JraW5nQ29weSwgbW9uaXRvcik7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBzZXRMYXVuY2hEZWZhdWx0cygpICIgKyB0b1N0cmluZygpLCBlKTsKCQl9Cgl9CgoJcHVibGljIHZvaWQgaW1wb3J0Q29uZmlndXJhdGlvbihJUnVudGltZSBydW50aW1lMiwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJdHJ5IHsKCQkJZ2V0RGVsZWdhdGUobW9uaXRvcikuaW1wb3J0Q29uZmlndXJhdGlvbihydW50aW1lMiwgbW9uaXRvcik7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBzZXRMYXVuY2hEZWZhdWx0cygpICIgKyB0b1N0cmluZygpLCBlKTsKCQl9Cgl9CgoJLyoqCgkgKiBSZXR1cm4gdGhlIGxhdW5jaCBjb25maWd1cmF0aW9uIGZvciB0aGlzIHNlcnZlci4gSWYgb25lIGRvZXMgbm90IGV4aXN0LCBpdAoJICogd2lsbCBiZSBjcmVhdGVkIGlmICJjcmVhdGUiIGlzIHRydWUsIGFuZCBvdGhlcndpc2Ugd2lsbCByZXR1cm4gbnVsbC4KCSAqIAoJICogQHBhcmFtIGNyZWF0ZSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIG5ldyBsYXVuY2ggY29uZmlndXJhdGlvbiBzaG91bGQgYmUKCSAqICAgIGNyZWF0ZWQgaWYgdGhlcmUgYXJlIG5vbmUgYWxyZWFkeQoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yLCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiBwcm9ncmVzcwoJICogICAgcmVwb3J0aW5nIGFuZCBjYW5jZWxsYXRpb24gYXJlIG5vdCBkZXNpcmVkCgkgKiBAcmV0dXJuIHRoZSBsYXVuY2ggY29uZmlndXJhdGlvbiwgbm8gPGNvZGU+bnVsbDwvY29kZT4gaWYgdGhlcmUgd2FzIG5vCgkgKiAgICBleGlzdGluZyBsYXVuY2ggY29uZmlndXJhdGlvbiBhbmQgPGNvZGU+Y3JlYXRlPC9jb2RlPiB3YXMgZmFsc2UKCSAqIEB0aHJvd3MgQ29yZUV4Y2VwdGlvbgoJICovCglwdWJsaWMgSUxhdW5jaENvbmZpZ3VyYXRpb24gZ2V0TGF1bmNoQ29uZmlndXJhdGlvbihib29sZWFuIGNyZWF0ZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJSUxhdW5jaENvbmZpZ3VyYXRpb25UeXBlIGxhdW5jaENvbmZpZ1R5cGUgPSAoKFNlcnZlclR5cGUpIGdldFNlcnZlclR5cGUoKSkuZ2V0TGF1bmNoQ29uZmlndXJhdGlvblR5cGUoKTsKCQkKCQlJTGF1bmNoTWFuYWdlciBsYXVuY2hNYW5hZ2VyID0gRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldExhdW5jaE1hbmFnZXIoKTsKCQlJTGF1bmNoQ29uZmlndXJhdGlvbltdIGxhdW5jaENvbmZpZ3MgPSBudWxsOwoJCXRyeSB7CgkJCWxhdW5jaENvbmZpZ3MgPSBsYXVuY2hNYW5hZ2VyLmdldExhdW5jaENvbmZpZ3VyYXRpb25zKGxhdW5jaENvbmZpZ1R5cGUpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJCgkJaWYgKGxhdW5jaENvbmZpZ3MgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IGxhdW5jaENvbmZpZ3MubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJdHJ5IHsKCQkJCQlTdHJpbmcgc2VydmVySWQgPSBsYXVuY2hDb25maWdzW2ldLmdldEF0dHJpYnV0ZShTRVJWRVJfSUQsIChTdHJpbmcpIG51bGwpOwoJCQkJCWlmIChnZXRJZCgpLmVxdWFscyhzZXJ2ZXJJZCkpIHsKCQkJCQkJSUxhdW5jaENvbmZpZ3VyYXRpb25Xb3JraW5nQ29weSB3YyA9IGxhdW5jaENvbmZpZ3NbaV0uZ2V0V29ya2luZ0NvcHkoKTsKCQkJCQkJc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKHdjLCBtb25pdG9yKTsKCQkJCQkJaWYgKHdjLmlzRGlydHkoKSkKCQkJCQkJCXJldHVybiB3Yy5kb1NhdmUoKTsKCQkJCQkJcmV0dXJuIGxhdW5jaENvbmZpZ3NbaV07CgkJCQkJfQoJCQkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY29uZmlndXJpbmcgbGF1bmNoIiwgZSk7CgkJCQl9CgkJCX0KCQl9CgkJCgkJaWYgKCFjcmVhdGUpCgkJCXJldHVybiBudWxsOwoJCQoJCS8vIGNyZWF0ZSBhIG5ldyBsYXVuY2ggY29uZmlndXJhdGlvbgoJCVN0cmluZyBsYXVuY2hOYW1lID0gZ2V0VmFsaWRMYXVuY2hDb25maWd1cmF0aW9uTmFtZShnZXROYW1lKCkpOwoJCWxhdW5jaE5hbWUgPSBsYXVuY2hNYW5hZ2VyLmdlbmVyYXRlVW5pcXVlTGF1bmNoQ29uZmlndXJhdGlvbk5hbWVGcm9tKGxhdW5jaE5hbWUpOyAKCQlJTGF1bmNoQ29uZmlndXJhdGlvbldvcmtpbmdDb3B5IHdjID0gbGF1bmNoQ29uZmlnVHlwZS5uZXdJbnN0YW5jZShudWxsLCBsYXVuY2hOYW1lKTsKCQl3Yy5zZXRBdHRyaWJ1dGUoU0VSVkVSX0lELCBnZXRJZCgpKTsKCQlzZXR1cExhdW5jaENvbmZpZ3VyYXRpb24od2MsIG1vbml0b3IpOwoJCXJldHVybiB3Yy5kb1NhdmUoKTsKCX0KCglwcm90ZWN0ZWQgU3RyaW5nIGdldFZhbGlkTGF1bmNoQ29uZmlndXJhdGlvbk5hbWUoU3RyaW5nIHMpIHsKCQlpZiAocyA9PSBudWxsIHx8IHMubGVuZ3RoKCkgPT0gMCkKCQkJcmV0dXJuICIxIjsKCQlpbnQgc2l6ZSA9IElOVkFMSURfQ0hBUlMubGVuZ3RoOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCXMgPSBzLnJlcGxhY2UoSU5WQUxJRF9DSEFSU1tpXSwgJ18nKTsKCQl9CgkJcmV0dXJuIHM7Cgl9CgoJLyoqCgkgKiBAc2VlIElTZXJ2ZXIjc3RhcnQoU3RyaW5nLCBJUHJvZ3Jlc3NNb25pdG9yKQoJICovCglwdWJsaWMgdm9pZCBzdGFydChTdHJpbmcgbW9kZTIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlN0YXJ0aW5nIHNlcnZlcjogIiArIHRvU3RyaW5nKCkgKyAiLCBsYXVuY2hNb2RlOiAiICsgbW9kZTIpOwoJCgkJdHJ5IHsKCQkJSUxhdW5jaENvbmZpZ3VyYXRpb24gbGF1bmNoQ29uZmlnID0gZ2V0TGF1bmNoQ29uZmlndXJhdGlvbih0cnVlLCBtb25pdG9yKTsKCQkJSUxhdW5jaCBsYXVuY2ggPSBsYXVuY2hDb25maWcubGF1bmNoKG1vZGUyLCBtb25pdG9yKTsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiTGF1bmNoOiAiICsgbGF1bmNoKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igc3RhcnRpbmcgc2VydmVyICIgKyB0b1N0cmluZygpLCBlKTsKCQkJdGhyb3cgZTsKCQl9Cgl9CgoJLyoqCgkgKiBDbGVhbiB1cCBhbnkgb2xkIGxhdW5jaCBjb25maWd1cmF0aW9ucyB3aXRoIHRoZSBjdXJyZW50IHNlcnZlcidzIGlkLgoJICovCglwcm90ZWN0ZWQgdm9pZCBkZWxldGVMYXVuY2hDb25maWd1cmF0aW9ucygpIHsKCQlpZiAoZ2V0U2VydmVyVHlwZSgpID09IG51bGwpCgkJCXJldHVybjsKCQlJTGF1bmNoTWFuYWdlciBsYXVuY2hNYW5hZ2VyID0gRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldExhdW5jaE1hbmFnZXIoKTsKCQlJTGF1bmNoQ29uZmlndXJhdGlvblR5cGUgbGF1bmNoQ29uZmlnVHlwZSA9ICgoU2VydmVyVHlwZSkgZ2V0U2VydmVyVHlwZSgpKS5nZXRMYXVuY2hDb25maWd1cmF0aW9uVHlwZSgpOwoJCQoJCUlMYXVuY2hDb25maWd1cmF0aW9uW10gY29uZmlncyA9IG51bGw7CgkJdHJ5IHsKCQkJY29uZmlncyA9IGxhdW5jaE1hbmFnZXIuZ2V0TGF1bmNoQ29uZmlndXJhdGlvbnMobGF1bmNoQ29uZmlnVHlwZSk7CgkJCWludCBzaXplID0gY29uZmlncy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQl0cnkgewoJCQkJCWlmIChnZXRJZCgpLmVxdWFscyhjb25maWdzW2ldLmdldEF0dHJpYnV0ZShTRVJWRVJfSUQsIChTdHJpbmcpIG51bGwpKSkKCQkJCQkJY29uZmlnc1tpXS5kZWxldGUoKTsKCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJLy8gaWdub3JlCgkJCQl9CgkJCX0KCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9Cgl9CgoJLyoqCgkgKiBAc2VlIElTZXJ2ZXIjY2FuUmVzdGFydChTdHJpbmcpCgkgKi8KCXB1YmxpYyBJU3RhdHVzIGNhblJlc3RhcnQoU3RyaW5nIG1vZGUyKSB7CgkJaWYgKCFnZXRTZXJ2ZXJUeXBlKCkuc3VwcG9ydHNMYXVuY2hNb2RlKG1vZGUyKSkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMuZXJyb3JMYXVuY2hNb2RlLCBudWxsKTsKCgkJaW50IHN0YXRlID0gZ2V0U2VydmVyU3RhdGUoKTsKCQlpZiAoc3RhdGUgPT0gU1RBVEVfU1RBUlRFRCkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMuY2FuUmVzdGFydE9rLCBudWxsKTsKCQkKCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5lcnJvclJlc3RhcnROb3RTdGFydGVkLCBudWxsKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGN1cnJlbnQgcmVzdGFydCBzdGF0ZSBvZiB0aGUgc2VydmVyLiBUaGlzCgkgKiBpbXBsZW1lbnRhdGlvbiB3aWxsIGFsd2F5cyByZXR1cm4gZmFsc2Ugd2hlbiB0aGUgc2VydmVyCgkgKiBpcyBzdG9wcGVkLgoJICoKCSAqIEByZXR1cm4gYm9vbGVhbgoJICovCglwdWJsaWMgYm9vbGVhbiBnZXRTZXJ2ZXJSZXN0YXJ0U3RhdGUoKSB7CgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuIGZhbHNlOwoJCXJldHVybiBzZXJ2ZXJSZXN0YXJ0TmVlZGVkOwoJfQoKCS8qKgoJICogU2V0cyB0aGUgc2VydmVyIHJlc3RhcnQgc3RhdGUuCgkgKgoJICogQHBhcmFtIHN0YXRlIGJvb2xlYW4KCSAqLwoJcHVibGljIHN5bmNocm9uaXplZCB2b2lkIHNldFNlcnZlclJlc3RhcnRTdGF0ZShib29sZWFuIHN0YXRlKSB7CgkJaWYgKHN0YXRlID09IHNlcnZlclJlc3RhcnROZWVkZWQpCgkJCXJldHVybjsKCQlzZXJ2ZXJSZXN0YXJ0TmVlZGVkID0gc3RhdGU7CgkJZmlyZVJlc3RhcnRTdGF0ZUNoYW5nZUV2ZW50KCk7Cgl9CgoJLyoqCgkgKiBAc2VlIElTZXJ2ZXIjcmVzdGFydChTdHJpbmcsIElQcm9ncmVzc01vbml0b3IpCgkgKi8KCXB1YmxpYyB2b2lkIHJlc3RhcnQoZmluYWwgU3RyaW5nIG1vZGUyLCBmaW5hbCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlpZiAoZ2V0U2VydmVyU3RhdGUoKSA9PSBTVEFURV9TVE9QUEVEKQoJCQlyZXR1cm47CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJSZXN0YXJ0aW5nIHNlcnZlcjogIiArIGdldE5hbWUoKSk7CgkKCQl0cnkgewoJCQl0cnkgewoJCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUobnVsbCkucmVzdGFydChtb2RlMik7CgkJCQlyZXR1cm47CgkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgcmVzdGFydCgpICIgKyB0b1N0cmluZygpKTsKCQkJfQoJCQoJCQkvLyBhZGQgbGlzdGVuZXIgdG8gc3RhcnQgaXQgYXMgc29vbiBhcyBpdCBpcyBzdG9wcGVkCgkJCWFkZFNlcnZlckxpc3RlbmVyKG5ldyBJU2VydmVyTGlzdGVuZXIoKSB7CgkJCQlwdWJsaWMgdm9pZCBzZXJ2ZXJDaGFuZ2VkKFNlcnZlckV2ZW50IGV2ZW50KSB7CgkJCQkJaW50IGV2ZW50S2luZCA9IGV2ZW50LmdldEtpbmQoKTsKCQkJCQlJU2VydmVyIHNlcnZlciA9IGV2ZW50LmdldFNlcnZlcigpOwoJCQkJCWlmIChldmVudEtpbmQgPT0gKFNlcnZlckV2ZW50LlNFUlZFUl9DSEFOR0UgfCBTZXJ2ZXJFdmVudC5TVEFURV9DSEFOR0UpKSB7CgkJCQkJCWlmIChzZXJ2ZXIuZ2V0U2VydmVyU3RhdGUoKSA9PSBTVEFURV9TVE9QUEVEKSB7CgkJCQkJCQlzZXJ2ZXIucmVtb3ZlU2VydmVyTGlzdGVuZXIodGhpcyk7CgoJCQkJCQkJLy8gcmVzdGFydCBpbiBhIHF1YXJ0ZXIgc2Vjb25kIChnaXZlIG90aGVyIGxpc3RlbmVycyBhIGNoYW5jZQoJCQkJCQkJLy8gdG8gaGVhciB0aGUgc3RvcHBlZCBtZXNzYWdlKQoJCQkJCQkJVGhyZWFkIHQgPSBuZXcgVGhyZWFkKCkgewoJCQkJCQkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCQkJCQkJdHJ5IHsKCQkJCQkJCQkJCVRocmVhZC5zbGVlcCgyNTApOwoJCQkJCQkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCQkJCQkJLy8gaWdub3JlCgkJCQkJCQkJCX0KCQkJCQkJCQkJdHJ5IHsKCQkJCQkJCQkJCVNlcnZlci50aGlzLnN0YXJ0KG1vZGUyLCBtb25pdG9yKTsKCQkJCQkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHdoaWxlIHJlc3RhcnRpbmcgc2VydmVyIiwgZSk7CgkJCQkJCQkJCX0KCQkJCQkJCQl9CgkJCQkJCQl9OwoJCQkJCQkJdC5zZXREYWVtb24odHJ1ZSk7CgkJCQkJCQl0LnNldFByaW9yaXR5KFRocmVhZC5OT1JNX1BSSU9SSVRZIC0gMik7CgkJCQkJCQl0LnN0YXJ0KCk7CgkJCQkJCX0KCQkJCQl9CgkJCQkJCgkJCQl9CgkJCX0pOwoJCgkJCS8vIHN0b3AgdGhlIHNlcnZlcgoJCQlzdG9wKGZhbHNlKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciByZXN0YXJ0aW5nIHNlcnZlciIsIGUpOwoJCX0KCX0KCgkvKioKCSAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc2VydmVyIGlzIGluIGEgc3RhdGUgdGhhdCBpdCBjYW4KCSAqIGJlIHN0b3BwZWQuCgkgKgoJICogQHJldHVybiBib29sZWFuCgkgKi8KCXB1YmxpYyBJU3RhdHVzIGNhblN0b3AoKSB7CgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTWVzc2FnZXMuZXJyb3JTdG9wQWxyZWFkeVN0b3BwZWQsIG51bGwpOwoKCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5jYW5TdG9wT2ssIG51bGwpOwoJfQoKCS8qKgoJICogQHNlZSBJU2VydmVyI3N0b3AoYm9vbGVhbikKCSAqLwoJcHVibGljIHZvaWQgc3RvcChib29sZWFuIGZvcmNlKSB7CgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuOwoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJTdG9wcGluZyBzZXJ2ZXI6ICIgKyB0b1N0cmluZygpKTsKCgkJdHJ5IHsKCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUobnVsbCkuc3RvcChmb3JjZSk7CgkJfSBjYXRjaCAoVGhyb3dhYmxlIHQpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBzdG9wKCkgIiArIHRvU3RyaW5nKCksIHQpOwoJCX0KCX0KCQoJLyoqCgkgKiBAc2VlIElTZXJ2ZXIjc3RhcnQoU3RyaW5nLCBJT3BlcmF0aW9uTGlzdGVuZXIpCgkgKi8KCXB1YmxpYyB2b2lkIHN0YXJ0KFN0cmluZyBtb2RlMiwgSU9wZXJhdGlvbkxpc3RlbmVyIGxpc3RlbmVyMikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzU3RhcnQgMSIpOwoJCWZpbmFsIE9iamVjdCBtdXRleCA9IG5ldyBPYmplY3QoKTsKCQoJCS8vIGFkZCBsaXN0ZW5lciB0byB0aGUgc2VydmVyCgkJSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IElTZXJ2ZXJMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgc2VydmVyQ2hhbmdlZChTZXJ2ZXJFdmVudCBldmVudCkgewoJCQkJaW50IGV2ZW50S2luZCA9IGV2ZW50LmdldEtpbmQoKTsKCQkJCUlTZXJ2ZXIgc2VydmVyID0gZXZlbnQuZ2V0U2VydmVyKCk7CgkJCQlpZiAoZXZlbnRLaW5kID09IChTZXJ2ZXJFdmVudC5TRVJWRVJfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFKSkgewoJCQkJCWludCBzdGF0ZSA9IHNlcnZlci5nZXRTZXJ2ZXJTdGF0ZSgpOwoJCQkJCWlmIChzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQgfHwgc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKSB7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJdHJ5IHsKCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IG5vdGlmeSIpOwoJCQkJCQkJCW11dGV4Lm5vdGlmeUFsbCgpOwoJCQkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBub3RpZnlpbmcgc2VydmVyIHN0YXJ0IiwgZSk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCWFkZFNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkKCQlmaW5hbCBpbnQgc2VydmVyVGltZW91dCA9ICgoU2VydmVyVHlwZSkgZ2V0U2VydmVyVHlwZSgpKS5nZXRTdGFydFRpbWVvdXQoKTsKCQljbGFzcyBUaW1lciB7CgkJCWJvb2xlYW4gdGltZW91dDsKCQkJYm9vbGVhbiBhbHJlYWR5RG9uZTsKCQl9CgkJZmluYWwgVGltZXIgdGltZXIgPSBuZXcgVGltZXIoKTsKCQkKCQlUaHJlYWQgdGhyZWFkID0gbmV3IFRocmVhZCgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJdHJ5IHsKCQkJCQlUaHJlYWQuc2xlZXAoc2VydmVyVGltZW91dCAqIDEwMDApOwoJCQkJCWlmICghdGltZXIuYWxyZWFkeURvbmUpIHsKCQkJCQkJdGltZXIudGltZW91dCA9IHRydWU7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNTdGFydCBub3RpZnkgdGltZW91dCIpOwoJCQkJCQkJbXV0ZXgubm90aWZ5QWxsKCk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIG5vdGlmeWluZyBzZXJ2ZXIgc3RhcnQgdGltZW91dCIsIGUpOwoJCQkJfQoJCQl9CgkJfTsKCQl0aHJlYWQuc2V0RGFlbW9uKHRydWUpOwoJCXRocmVhZC5zdGFydCgpOwoJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNTdGFydCAyIik7CgkKCQkvLyBzdGFydCB0aGUgc2VydmVyCgkJdHJ5IHsKCQkJc3RhcnQobW9kZTIsIChJUHJvZ3Jlc3NNb25pdG9yKW51bGwpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQlyZW1vdmVTZXJ2ZXJMaXN0ZW5lcihsaXN0ZW5lcik7CgkJCXRpbWVyLmFscmVhZHlEb25lID0gdHJ1ZTsKCQkJbGlzdGVuZXIyLmRvbmUoZS5nZXRTdGF0dXMoKSk7CgkJCXJldHVybjsKCQl9CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IDMiKTsKCQoJCS8vIHdhaXQgZm9yIGl0ISB3YWl0IGZvciBpdCEgLi4uCgkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQl0cnkgewoJCQkJd2hpbGUgKCF0aW1lci50aW1lb3V0ICYmICEoZ2V0U2VydmVyU3RhdGUoKSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQgfHwgZ2V0U2VydmVyU3RhdGUoKSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpKQoJCQkJCW11dGV4LndhaXQoKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHdhaXRpbmcgZm9yIHNlcnZlciBzdGFydCIsIGUpOwoJCQl9CgkJfQoJCXJlbW92ZVNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKHRpbWVyLnRpbWVvdXQpIHsKCQkJbGlzdGVuZXIyLmRvbmUobmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBOTFMuYmluZChNZXNzYWdlcy5lcnJvclN0YXJ0VGltZW91dCwgbmV3IFN0cmluZ1tdIHsgZ2V0TmFtZSgpLCBzZXJ2ZXJUaW1lb3V0ICsgIiIgfSksIG51bGwpKTsKCQkJcmV0dXJuOwoJCX0KCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKSB7CgkJCWxpc3RlbmVyMi5kb25lKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTkxTLmJpbmQoTWVzc2FnZXMuZXJyb3JTdGFydEZhaWxlZCwgZ2V0TmFtZSgpKSwgbnVsbCkpOwoJCQlyZXR1cm47CgkJfQoJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNTdGFydCA0Iik7CgkJbGlzdGVuZXIyLmRvbmUobnVsbCk7Cgl9CgoJcHVibGljIHZvaWQgc3luY2hyb25vdXNTdGFydChTdHJpbmcgbW9kZTIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzU3RhcnQgMSIpOwoJCWZpbmFsIE9iamVjdCBtdXRleCA9IG5ldyBPYmplY3QoKTsKCQoJCS8vIGFkZCBsaXN0ZW5lciB0byB0aGUgc2VydmVyCgkJSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IElTZXJ2ZXJMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgc2VydmVyQ2hhbmdlZChTZXJ2ZXJFdmVudCBldmVudCkgewoJCQkJaW50IGV2ZW50S2luZCA9IGV2ZW50LmdldEtpbmQoKTsKCQkJCUlTZXJ2ZXIgc2VydmVyID0gZXZlbnQuZ2V0U2VydmVyKCk7CgkJCQlpZiAoZXZlbnRLaW5kID09IChTZXJ2ZXJFdmVudC5TRVJWRVJfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFKSkgewoJCQkJCWludCBzdGF0ZSA9IHNlcnZlci5nZXRTZXJ2ZXJTdGF0ZSgpOwoJCQkJCWlmIChzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQgfHwgc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKSB7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJdHJ5IHsKCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IG5vdGlmeSIpOwoJCQkJCQkJCW11dGV4Lm5vdGlmeUFsbCgpOwoJCQkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBub3RpZnlpbmcgc2VydmVyIHN0YXJ0IiwgZSk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCWFkZFNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkKCQlmaW5hbCBpbnQgc2VydmVyVGltZW91dCA9ICgoU2VydmVyVHlwZSkgZ2V0U2VydmVyVHlwZSgpKS5nZXRTdGFydFRpbWVvdXQoKTsKCQljbGFzcyBUaW1lciB7CgkJCWJvb2xlYW4gdGltZW91dDsKCQkJYm9vbGVhbiBhbHJlYWR5RG9uZTsKCQl9CgkJZmluYWwgVGltZXIgdGltZXIgPSBuZXcgVGltZXIoKTsKCQkKCQlUaHJlYWQgdGhyZWFkID0gbmV3IFRocmVhZCgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJdHJ5IHsKCQkJCQlUaHJlYWQuc2xlZXAoc2VydmVyVGltZW91dCAqIDEwMDApOwoJCQkJCWlmICghdGltZXIuYWxyZWFkeURvbmUpIHsKCQkJCQkJdGltZXIudGltZW91dCA9IHRydWU7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNTdGFydCBub3RpZnkgdGltZW91dCIpOwoJCQkJCQkJbXV0ZXgubm90aWZ5QWxsKCk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIG5vdGlmeWluZyBzZXJ2ZXIgc3RhcnQgdGltZW91dCIsIGUpOwoJCQkJfQoJCQl9CgkJfTsKCQl0aHJlYWQuc2V0RGFlbW9uKHRydWUpOwoJCXRocmVhZC5zdGFydCgpOwoJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNTdGFydCAyIik7CgkKCQkvLyBzdGFydCB0aGUgc2VydmVyCgkJdHJ5IHsKCQkJc3RhcnQobW9kZTIsIG1vbml0b3IpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQlyZW1vdmVTZXJ2ZXJMaXN0ZW5lcihsaXN0ZW5lcik7CgkJCXRpbWVyLmFscmVhZHlEb25lID0gdHJ1ZTsKCQkJdGhyb3cgZTsKCQl9CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IDMiKTsKCQoJCS8vIHdhaXQgZm9yIGl0ISB3YWl0IGZvciBpdCEgLi4uCgkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQl0cnkgewoJCQkJd2hpbGUgKCF0aW1lci50aW1lb3V0ICYmICEoZ2V0U2VydmVyU3RhdGUoKSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQgfHwgZ2V0U2VydmVyU3RhdGUoKSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpKQoJCQkJCW11dGV4LndhaXQoKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHdhaXRpbmcgZm9yIHNlcnZlciBzdGFydCIsIGUpOwoJCQl9CgkJfQoJCXJlbW92ZVNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKHRpbWVyLnRpbWVvdXQpCgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTkxTLmJpbmQoTWVzc2FnZXMuZXJyb3JTdGFydFRpbWVvdXQsIG5ldyBTdHJpbmdbXSB7IGdldE5hbWUoKSwgc2VydmVyVGltZW91dCArICIiIH0pLCBudWxsKSk7CgkJdGltZXIuYWxyZWFkeURvbmUgPSB0cnVlOwoJCQoJCWlmIChnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBOTFMuYmluZChNZXNzYWdlcy5lcnJvclN0YXJ0RmFpbGVkLCBnZXROYW1lKCkpLCBudWxsKSk7CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IDQiKTsKCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI3N5bmNocm9ub3VzUmVzdGFydChTdHJpbmcsIElQcm9ncmVzc01vbml0b3IpCgkgKi8KCXB1YmxpYyB2b2lkIHN5bmNocm9ub3VzUmVzdGFydChTdHJpbmcgbW9kZTIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXN5bmNocm9ub3VzU3RvcCh0cnVlKTsKCQlzeW5jaHJvbm91c1N0YXJ0KG1vZGUyLCBtb25pdG9yKTsKCX0KCQoJLyoKCSAqIEBzZWUgSVNlcnZlciNyZXN0YXJ0KFN0cmluZywgSU9wZXJhdGlvbkxpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCByZXN0YXJ0KFN0cmluZyBtb2RlMiwgSU9wZXJhdGlvbkxpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3RvcCh0cnVlLCBudWxsKTsKCQl0cnkgewoJCQlzdGFydChtb2RlMiwgKElQcm9ncmVzc01vbml0b3IpbnVsbCk7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQkvLyBUT0RPCgkJfQoJCWxpc3RlbmVyLmRvbmUobnVsbCk7Cgl9CgkKCS8qCgkgKiBAc2VlIElTZXJ2ZXIjc3RvcChib29sZWFuLCBJT3BlcmF0aW9uTGlzdGVuZXIpCgkgKi8KCXB1YmxpYyB2b2lkIHN0b3AoYm9vbGVhbiBmb3JjZSwgSU9wZXJhdGlvbkxpc3RlbmVyIGxpc3RlbmVyMikgewoJCWlmIChnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuOwoJCQoJCWZpbmFsIE9iamVjdCBtdXRleCA9IG5ldyBPYmplY3QoKTsKCQoJCS8vIGFkZCBsaXN0ZW5lciB0byB0aGUgc2VydmVyCgkJSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IElTZXJ2ZXJMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgc2VydmVyQ2hhbmdlZChTZXJ2ZXJFdmVudCBldmVudCkgewoJCQkJaW50IGV2ZW50S2luZCA9IGV2ZW50LmdldEtpbmQoKTsKCQkJCUlTZXJ2ZXIgc2VydmVyID0gZXZlbnQuZ2V0U2VydmVyKCk7CgkJCQlpZiAoZXZlbnRLaW5kID09IChTZXJ2ZXJFdmVudC5TRVJWRVJfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFKSkgewoJCQkJCWludCBzdGF0ZSA9IHNlcnZlci5nZXRTZXJ2ZXJTdGF0ZSgpOwoJCQkJCWlmIChTZXJ2ZXIudGhpcyA9PSBzZXJ2ZXIgJiYgc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKSB7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJdHJ5IHsKCQkJCQkJCQltdXRleC5ub3RpZnlBbGwoKTsKCQkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igbm90aWZ5aW5nIHNlcnZlciBzdG9wIiwgZSk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCWFkZFNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkKCQljbGFzcyBUaW1lciB7CgkJCWJvb2xlYW4gdGltZW91dDsKCQkJYm9vbGVhbiBhbHJlYWR5RG9uZTsKCQl9CgkJZmluYWwgVGltZXIgdGltZXIgPSBuZXcgVGltZXIoKTsKCQkKCQlUaHJlYWQgdGhyZWFkID0gbmV3IFRocmVhZCgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJdHJ5IHsKCQkJCQlUaHJlYWQuc2xlZXAoMTIwMDAwKTsKCQkJCQlpZiAoIXRpbWVyLmFscmVhZHlEb25lKSB7CgkJCQkJCXRpbWVyLnRpbWVvdXQgPSB0cnVlOwoJCQkJCQkvLyBub3RpZnkgd2FpdGVyCgkJCQkJCXN5bmNocm9uaXplZCAobXV0ZXgpIHsKCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN0b3Agbm90aWZ5IHRpbWVvdXQiKTsKCQkJCQkJCW11dGV4Lm5vdGlmeUFsbCgpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBub3RpZnlpbmcgc2VydmVyIHN0b3AgdGltZW91dCIsIGUpOwoJCQkJfQoJCQl9CgkJfTsKCQl0aHJlYWQuc2V0RGFlbW9uKHRydWUpOwoJCXRocmVhZC5zdGFydCgpOwoJCgkJLy8gc3RvcCB0aGUgc2VydmVyCgkJc3RvcChmb3JjZSk7CgkKCQkvLyB3YWl0IGZvciBpdCEgd2FpdCBmb3IgaXQhCgkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQl0cnkgewoJCQkJd2hpbGUgKCF0aW1lci50aW1lb3V0ICYmIGdldFNlcnZlclN0YXRlKCkgIT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQkJCW11dGV4LndhaXQoKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHdhaXRpbmcgZm9yIHNlcnZlciBzdG9wIiwgZSk7CgkJCX0KCQl9CgkJcmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCQoJCS8qCgkJLy9jYW4ndCB0aHJvdyBleGNlcHRpb25zCgkJaWYgKHRpbWVyLnRpbWVvdXQpCgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyQ29yZS5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yU3RhcnRGYWlsZWQiLCBnZXROYW1lKCkpLCBudWxsKSk7CgkJZWxzZQoJCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlckNvcmUuUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvclN0YXJ0RmFpbGVkIiwgZ2V0TmFtZSgpKSwgbnVsbCkpOyovCgkJbGlzdGVuZXIyLmRvbmUobnVsbCk7Cgl9CgoJLyoKCSAqIEBzZWUgSVNlcnZlciNzeW5jaHJvbm91c1N0b3AoKQoJICovCglwdWJsaWMgdm9pZCBzeW5jaHJvbm91c1N0b3AoYm9vbGVhbiBmb3JjZSkgewoJCWlmIChnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuOwoJCQoJCWZpbmFsIE9iamVjdCBtdXRleCA9IG5ldyBPYmplY3QoKTsKCQoJCS8vIGFkZCBsaXN0ZW5lciB0byB0aGUgc2VydmVyCgkJSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IElTZXJ2ZXJMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgc2VydmVyQ2hhbmdlZChTZXJ2ZXJFdmVudCBldmVudCkgewoJCQkJaW50IGV2ZW50S2luZCA9IGV2ZW50LmdldEtpbmQoKTsKCQkJCUlTZXJ2ZXIgc2VydmVyID0gZXZlbnQuZ2V0U2VydmVyKCk7CgkJCQlpZiAoZXZlbnRLaW5kID09IChTZXJ2ZXJFdmVudC5TRVJWRVJfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFKSkgewoJCQkJCWludCBzdGF0ZSA9IHNlcnZlci5nZXRTZXJ2ZXJTdGF0ZSgpOwoJCQkJCWlmIChTZXJ2ZXIudGhpcyA9PSBzZXJ2ZXIgJiYgc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKSB7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJdHJ5IHsKCQkJCQkJCQltdXRleC5ub3RpZnlBbGwoKTsKCQkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igbm90aWZ5aW5nIHNlcnZlciBzdG9wIiwgZSk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCWFkZFNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkKCQljbGFzcyBUaW1lciB7CgkJCWJvb2xlYW4gdGltZW91dDsKCQkJYm9vbGVhbiBhbHJlYWR5RG9uZTsKCQl9CgkJZmluYWwgVGltZXIgdGltZXIgPSBuZXcgVGltZXIoKTsKCQkKCQlUaHJlYWQgdGhyZWFkID0gbmV3IFRocmVhZCgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJdHJ5IHsKCQkJCQlUaHJlYWQuc2xlZXAoMTIwMDAwKTsKCQkJCQlpZiAoIXRpbWVyLmFscmVhZHlEb25lKSB7CgkJCQkJCXRpbWVyLnRpbWVvdXQgPSB0cnVlOwoJCQkJCQkvLyBub3RpZnkgd2FpdGVyCgkJCQkJCXN5bmNocm9uaXplZCAobXV0ZXgpIHsKCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN0b3Agbm90aWZ5IHRpbWVvdXQiKTsKCQkJCQkJCW11dGV4Lm5vdGlmeUFsbCgpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBub3RpZnlpbmcgc2VydmVyIHN0b3AgdGltZW91dCIsIGUpOwoJCQkJfQoJCQl9CgkJfTsKCQl0aHJlYWQuc2V0RGFlbW9uKHRydWUpOwoJCXRocmVhZC5zdGFydCgpOwoJCgkJLy8gc3RvcCB0aGUgc2VydmVyCgkJc3RvcChmb3JjZSk7CgkKCQkvLyB3YWl0IGZvciBpdCEgd2FpdCBmb3IgaXQhCgkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQl0cnkgewoJCQkJd2hpbGUgKCF0aW1lci50aW1lb3V0ICYmIGdldFNlcnZlclN0YXRlKCkgIT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQkJCW11dGV4LndhaXQoKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHdhaXRpbmcgZm9yIHNlcnZlciBzdG9wIiwgZSk7CgkJCX0KCQl9CgkJcmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCQoJCS8qCgkJLy9jYW4ndCB0aHJvdyBleGNlcHRpb25zCgkJaWYgKHRpbWVyLnRpbWVvdXQpCgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyQ29yZS5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yU3RhcnRGYWlsZWQiLCBnZXROYW1lKCkpLCBudWxsKSk7CgkJZWxzZQoJCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlckNvcmUuUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvclN0YXJ0RmFpbGVkIiwgZ2V0TmFtZSgpKSwgbnVsbCkpOyovCgl9CgkKCS8qCgkgKiBUcmlnZ2VyIGEgcmVzdGFydCBvZiB0aGUgZ2l2ZW4gbW9kdWxlIGFuZCB3YWl0IHVudGlsIGl0IGhhcyBmaW5pc2hlZCByZXN0YXJ0aW5nLgoJICoKCSAqIEBwYXJhbSBtb2R1bGUgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklNb2R1bGUKCSAqIEBwYXJhbSBtb25pdG9yIG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5JUHJvZ3Jlc3NNb25pdG9yCgkgKiBAZXhjZXB0aW9uIG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5Db3JlRXhjZXB0aW9uIC0gdGhyb3duIGlmIGFuIGVycm9yIG9jY3VycyB3aGlsZSB0cnlpbmcgdG8gcmVzdGFydCB0aGUgbW9kdWxlCgkgKgoJcHVibGljIHZvaWQgc3luY2hyb25vdXNSZXN0YXJ0TW9kdWxlKGZpbmFsIElNb2R1bGVbXSBtb2R1bGUsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzTW9kdWxlUmVzdGFydCAxIik7CgoJCWZpbmFsIE9iamVjdCBtdXRleCA9IG5ldyBPYmplY3QoKTsKCQoJCS8vIGFkZCBsaXN0ZW5lciB0byB0aGUgbW9kdWxlCgkJSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IElTZXJ2ZXJMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgc2VydmVyQ2hhbmdlZChTZXJ2ZXJFdmVudCBldmVudCkgewoJCQkJaW50IGV2ZW50S2luZCA9IGV2ZW50LmdldEtpbmQoKTsKCQkJCUlTZXJ2ZXIgc2VydmVyID0gZXZlbnQuZ2V0U2VydmVyKCk7CgkJCQlpZiAoZXZlbnRLaW5kID09IChTZXJ2ZXJFdmVudC5NT0RVTEVfQ0hBTkdFIHwgU2VydmVyRXZlbnQuU1RBVEVfQ0hBTkdFKSkgewoJCQkJCWludCBzdGF0ZSA9IHNlcnZlci5nZXRNb2R1bGVTdGF0ZShtb2R1bGUpOwoJCQkJCWlmIChzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQgfHwgc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKSB7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJdHJ5IHsKCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c01vZHVsZVJlc3RhcnQgbm90aWZ5Iik7CgkJCQkJCQkJbXV0ZXgubm90aWZ5QWxsKCk7CgkJCQkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIG5vdGlmeWluZyBtb2R1bGUgcmVzdGFydCIsIGUpOwoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQl9CgkJfTsKCQlhZGRTZXJ2ZXJMaXN0ZW5lcihsaXN0ZW5lcik7CgkJCgkJLy8gbWFrZSBzdXJlIGl0IHRpbWVzIG91dCBhZnRlciAzMHMKCQljbGFzcyBUaW1lciB7CgkJCWJvb2xlYW4gdGltZW91dDsKCQkJYm9vbGVhbiBhbHJlYWR5RG9uZTsKCQl9CgkJZmluYWwgVGltZXIgdGltZXIgPSBuZXcgVGltZXIoKTsKCQkKCQlUaHJlYWQgdGhyZWFkID0gbmV3IFRocmVhZCgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJdHJ5IHsKCQkJCQlUaHJlYWQuc2xlZXAoMzAwMDApOwoJCQkJCWlmICghdGltZXIuYWxyZWFkeURvbmUpIHsKCQkJCQkJdGltZXIudGltZW91dCA9IHRydWU7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNNb2R1bGVSZXN0YXJ0IG5vdGlmeSB0aW1lb3V0Iik7CgkJCQkJCQltdXRleC5ub3RpZnlBbGwoKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igbm90aWZ5aW5nIG1vZHVsZSByZXN0YXJ0IHRpbWVvdXQiLCBlKTsKCQkJCX0KCQkJfQoJCX07CgkJdGhyZWFkLnNldERhZW1vbih0cnVlKTsKCQl0aHJlYWQuc3RhcnQoKTsKCQoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzTW9kdWxlUmVzdGFydCAyIik7CgkKCQkvLyByZXN0YXJ0IHRoZSBtb2R1bGUKCQl0cnkgewoJCQlnZXRCZWhhdmlvdXJEZWxlZ2F0ZShudWxsKS5yZXN0YXJ0TW9kdWxlKG1vZHVsZSwgbW9uaXRvcik7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCXJlbW92ZVNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkJdGhyb3cgZTsKCQl9CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c01vZHVsZVJlc3RhcnQgMyIpOwoJCgkJLy8gd2FpdCBmb3IgaXQhIHdhaXQgZm9yIGl0ISAuLi4KCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCXRyeSB7CgkJCQl3aGlsZSAoIXRpbWVyLnRpbWVvdXQgJiYgIShnZXRNb2R1bGVTdGF0ZShtb2R1bGUpID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCB8fCBnZXRNb2R1bGVTdGF0ZShtb2R1bGUpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkpCgkJCQkJbXV0ZXgud2FpdCgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igd2FpdGluZyBmb3Igc2VydmVyIHN0YXJ0IiwgZSk7CgkJCX0KCQl9CgkJcmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCWlmICh0aW1lci50aW1lb3V0KQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE5MUy5iaW5kKE1lc3NhZ2VzLmVycm9yTW9kdWxlUmVzdGFydEZhaWxlZCwgZ2V0TmFtZSgpKSwgbnVsbCkpOwoJCXRpbWVyLmFscmVhZHlEb25lID0gdHJ1ZTsKCQkKCQlpZiAoZ2V0TW9kdWxlU3RhdGUobW9kdWxlKSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpCgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTkxTLmJpbmQoTWVzc2FnZXMuZXJyb3JNb2R1bGVSZXN0YXJ0RmFpbGVkLCBnZXROYW1lKCkpLCBudWxsKSk7CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c01vZHVsZVJlc3RhcnQgNCIpOwoJfSovCgoJcHVibGljIElQYXRoIGdldFRlbXBEaXJlY3RvcnkoKSB7CgkJcmV0dXJuIFNlcnZlclBsdWdpbi5nZXRJbnN0YW5jZSgpLmdldFRlbXBEaXJlY3RvcnkoZ2V0SWQoKSk7Cgl9CgoJcHJvdGVjdGVkIFN0cmluZyBnZXRYTUxSb290KCkgewoJCXJldHVybiAic2VydmVyIjsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgbG9hZFN0YXRlKElNZW1lbnRvIG1lbWVudG8pIHsKCQkvKlN0cmluZyBzZXJ2ZXJUeXBlSWQgPSBtZW1lbnRvLmdldFN0cmluZygic2VydmVyLXR5cGUtaWQiKTsKCQlzZXJ2ZXJUeXBlID0gU2VydmVyQ29yZS5nZXRTZXJ2ZXJUeXBlKHNlcnZlclR5cGVJZCk7CgkJCgkJU3RyaW5nIHJ1bnRpbWVJZCA9IG1lbWVudG8uZ2V0U3RyaW5nKCJydW50aW1lLWlkIik7CgkJcnVudGltZSA9IFNlcnZlckNvcmUuZ2V0UmVzb3VyY2VNYW5hZ2VyKCkuZ2V0UnVudGltZShydW50aW1lSWQpOwoJCQoJCVN0cmluZyBjb25maWd1cmF0aW9uSWQgPSBtZW1lbnRvLmdldFN0cmluZygiY29uZmlndXJhdGlvbi1pZCIpOwoJCWNvbmZpZ3VyYXRpb24gPSBTZXJ2ZXJDb3JlLmdldFJlc291cmNlTWFuYWdlcigpLmdldFNlcnZlckNvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbklkKTsqLwoJCXJlc29sdmUoKTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgcmVzb2x2ZSgpIHsKCQlJU2VydmVyVHlwZSBvbGRTZXJ2ZXJUeXBlID0gc2VydmVyVHlwZTsKCQlTdHJpbmcgc2VydmVyVHlwZUlkID0gZ2V0QXR0cmlidXRlKCJzZXJ2ZXItdHlwZS1pZCIsIChTdHJpbmcpbnVsbCk7CgkJaWYgKHNlcnZlclR5cGVJZCAhPSBudWxsKQoJCQlzZXJ2ZXJUeXBlID0gU2VydmVyQ29yZS5maW5kU2VydmVyVHlwZShzZXJ2ZXJUeXBlSWQpOwoJCWVsc2UKCQkJc2VydmVyVHlwZSA9IG51bGw7CgkJaWYgKHNlcnZlclR5cGUgIT0gbnVsbCAmJiAhc2VydmVyVHlwZS5lcXVhbHMob2xkU2VydmVyVHlwZSkpCgkJCXNlcnZlclN0YXRlID0gKChTZXJ2ZXJUeXBlKXNlcnZlclR5cGUpLmdldEluaXRpYWxTdGF0ZSgpOwoJCQoJCVN0cmluZyBydW50aW1lSWQgPSBnZXRBdHRyaWJ1dGUoUlVOVElNRV9JRCwgKFN0cmluZyludWxsKTsKCQlpZiAocnVudGltZUlkICE9IG51bGwpCgkJCXJ1bnRpbWUgPSBTZXJ2ZXJDb3JlLmZpbmRSdW50aW1lKHJ1bnRpbWVJZCk7CgkJCgkJU3RyaW5nIGNvbmZpZ1BhdGggPSBnZXRBdHRyaWJ1dGUoQ09ORklHVVJBVElPTl9JRCwgKFN0cmluZyludWxsKTsKCQljb25maWd1cmF0aW9uID0gbnVsbDsKCQlpZiAoY29uZmlnUGF0aCAhPSBudWxsKQoJCQljb25maWd1cmF0aW9uID0gUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpLmdldFJvb3QoKS5nZXRGb2xkZXIobmV3IFBhdGgoY29uZmlnUGF0aCkpOwoJfQoKCXByb3RlY3RlZCB2b2lkIHNldEludGVybmFsKFNlcnZlcldvcmtpbmdDb3B5IHdjKSB7CgkJbWFwID0gd2MubWFwOwoJCWNvbmZpZ3VyYXRpb24gPSB3Yy5jb25maWd1cmF0aW9uOwoJCXJ1bnRpbWUgPSB3Yy5ydW50aW1lOwoJCXNlcnZlclN5bmNTdGF0ZSA9IHdjLnNlcnZlclN5bmNTdGF0ZTsKCQkvL3Jlc3RhcnROZWVkZWQgPSB3Yy5yZXN0YXJ0TmVlZGVkOwoJCXNlcnZlclR5cGUgPSB3Yy5zZXJ2ZXJUeXBlOwoJCW1vZHVsZXMgPSB3Yy5tb2R1bGVzOwoKCQkvLyBjYW4gbmV2ZXIgbW9kaWZ5IHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB2aWEgdGhlIHdvcmtpbmcgY29weQoJCS8vc2VydmVyU3RhdGUgPSB3Yy5zZXJ2ZXJTdGF0ZTsKCQlkZWxlZ2F0ZSA9IHdjLmRlbGVnYXRlOwoJfQoKCXByb3RlY3RlZCB2b2lkIHNhdmVTdGF0ZShJTWVtZW50byBtZW1lbnRvKSB7CgkJaWYgKHNlcnZlclR5cGUgIT0gbnVsbCkKCQkJbWVtZW50by5wdXRTdHJpbmcoInNlcnZlci10eXBlIiwgc2VydmVyVHlwZS5nZXRJZCgpKTsKCgkJaWYgKGNvbmZpZ3VyYXRpb24gIT0gbnVsbCkKCQkJbWVtZW50by5wdXRTdHJpbmcoQ09ORklHVVJBVElPTl9JRCwgY29uZmlndXJhdGlvbi5nZXRGdWxsUGF0aCgpLnRvU3RyaW5nKCkpOwoJCWVsc2UKCQkJbWVtZW50by5wdXRTdHJpbmcoQ09ORklHVVJBVElPTl9JRCwgbnVsbCk7CgkJCgkJaWYgKHJ1bnRpbWUgIT0gbnVsbCkKCQkJbWVtZW50by5wdXRTdHJpbmcoUlVOVElNRV9JRCwgcnVudGltZS5nZXRJZCgpKTsKCQllbHNlCgkJCW1lbWVudG8ucHV0U3RyaW5nKFJVTlRJTUVfSUQsIG51bGwpOwoJfQoKCS8qcHVibGljIHZvaWQgdXBkYXRlQ29uZmlndXJhdGlvbigpIHsKCQl0cnkgewoJCQlnZXREZWxlZ2F0ZShudWxsKS51cGRhdGVDb25maWd1cmF0aW9uKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSB1cGRhdGVDb25maWd1cmF0aW9uKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCX0KCX0qLwoJCgkvKiAobm9uLUphdmFkb2MpCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5JU2VydmVyQ29uZmlndXJhdGlvbiNjYW5Nb2RpZnlNb2R1bGUob3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLm1vZGVsLklNb2R1bGUpCgkgKi8KCXB1YmxpYyBJU3RhdHVzIGNhbk1vZGlmeU1vZHVsZXMoSU1vZHVsZVtdIGFkZCwgSU1vZHVsZVtdIHJlbW92ZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKGFkZCA9PSBudWxsICYmIHJlbW92ZSA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJBZGQgYW5kIHJlbW92ZSBjYW5ub3QgYm90aCBiZSBudWxsIik7CgkJdHJ5IHsKCQkJcmV0dXJuIGdldERlbGVnYXRlKG1vbml0b3IpLmNhbk1vZGlmeU1vZHVsZXMoYWRkLCByZW1vdmUpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgY2FuTW9kaWZ5TW9kdWxlcygpICIgKyB0b1N0cmluZygpLCBlKTsKCQkJcmV0dXJuIG51bGw7CgkJfQoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklTZXJ2ZXIjZ2V0TW9kdWxlcygpCgkgKi8KCXB1YmxpYyBJTW9kdWxlW10gZ2V0TW9kdWxlcygpIHsKCQlpZiAobW9kdWxlcyA9PSBudWxsKSB7CgkJCS8vIGNvbnZlcnQgZnJvbSBhdHRyaWJ1dGUKCQkJTGlzdCBsaXN0ID0gZ2V0QXR0cmlidXRlKE1PRFVMRV9MSVNULCAoTGlzdCkgbnVsbCk7CgkJCWlmIChsaXN0ID09IG51bGwpCgkJCQlsaXN0ID0gbmV3IEFycmF5TGlzdCgxKTsKCQkJCgkJCW1vZHVsZXMgPSBuZXcgQXJyYXlMaXN0KGxpc3Quc2l6ZSgpICsgMSk7CgkJCUl0ZXJhdG9yIGl0ZXJhdG9yID0gbGlzdC5pdGVyYXRvcigpOwoJCQl3aGlsZSAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCQlTdHJpbmcgbW9kdWxlU3RyID0gKFN0cmluZykgaXRlcmF0b3IubmV4dCgpOwoJCQkJSU1vZHVsZSBtb2R1bGUgPSBTZXJ2ZXJVdGlsLmdldE1vZHVsZShtb2R1bGVTdHIpOwoJCQkJaWYgKG1vZHVsZSAhPSBudWxsKQoJCQkJCW1vZHVsZXMuYWRkKG1vZHVsZSk7CgkJCX0KCQl9IGVsc2UgewoJCQkvLyB2ZXJpZnkgbW9kdWxlcyBhcmUgc3RpbGwgYXZhaWxhYmxlCgkJCUxpc3QgcmVtb3ZlID0gbmV3IEFycmF5TGlzdCgpOwoJCQlJdGVyYXRvciBpdGVyYXRvciA9IG1vZHVsZXMuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQkJSU1vZHVsZSBtb2R1bGUgPSAoSU1vZHVsZSkgaXRlcmF0b3IubmV4dCgpOwoJCQkJaWYgKFNlcnZlclV0aWwuZ2V0TW9kdWxlKG1vZHVsZS5nZXRJZCgpKSA9PSBudWxsKQoJCQkJCXJlbW92ZS5hZGQobW9kdWxlKTsKCQkJfQoJCQkKCQkJaXRlcmF0b3IgPSByZW1vdmUuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQkJbW9kdWxlcy5yZW1vdmUoaXRlcmF0b3IubmV4dCgpKTsKCQkJfQoJCX0KCQkKCQlJTW9kdWxlW10gbW9kdWxlczIgPSBuZXcgSU1vZHVsZVttb2R1bGVzLnNpemUoKV07CgkJbW9kdWxlcy50b0FycmF5KG1vZHVsZXMyKTsKCQlyZXR1cm4gbW9kdWxlczI7Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlciNnZXRNb2R1bGVTdGF0ZSgpCgkgKi8KCXB1YmxpYyBpbnQgZ2V0TW9kdWxlU3RhdGUoSU1vZHVsZVtdIG1vZHVsZSkgewoJCWlmIChtb2R1bGUgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTW9kdWxlIGNhbm5vdCBiZSBudWxsIik7CgkJdHJ5IHsKCQkJSW50ZWdlciBpbiA9IChJbnRlZ2VyKSBtb2R1bGVTdGF0ZS5nZXQoZ2V0S2V5KG1vZHVsZSkpOwoJCQlpZiAoaW4gIT0gbnVsbCkKCQkJCXJldHVybiBpbi5pbnRWYWx1ZSgpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCS8vIGlnbm9yZQoJCX0KCQlyZXR1cm4gU1RBVEVfVU5LTk9XTjsKCX0KCgkvKiAobm9uLUphdmFkb2MpCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5JU2VydmVyI2dldE1vZHVsZVN0YXRlKCkKCSAqLwoJcHVibGljIGludCBnZXRNb2R1bGVQdWJsaXNoU3RhdGUoSU1vZHVsZVtdIG1vZHVsZSkgewoJCWlmIChtb2R1bGUgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTW9kdWxlIGNhbm5vdCBiZSBudWxsIik7CgkJdHJ5IHsKCQkJSW50ZWdlciBpbiA9IChJbnRlZ2VyKSBtb2R1bGVQdWJsaXNoU3RhdGUuZ2V0KGdldEtleShtb2R1bGUpKTsKCQkJaWYgKGluICE9IG51bGwpCgkJCQlyZXR1cm4gaW4uaW50VmFsdWUoKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJcmV0dXJuIFBVQkxJU0hfU1RBVEVfVU5LTk9XTjsKCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI2dldENoaWxkTW9kdWxlKElNb2R1bGVbXSkKCSAqLwoJcHVibGljIElNb2R1bGVbXSBnZXRDaGlsZE1vZHVsZXMoSU1vZHVsZVtdIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJNb2R1bGUgY2Fubm90IGJlIG51bGwiKTsKCQl0cnkgewoJCQlyZXR1cm4gZ2V0RGVsZWdhdGUobW9uaXRvcikuZ2V0Q2hpbGRNb2R1bGVzKG1vZHVsZSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBnZXRDaGlsZE1vZHVsZXMoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXJldHVybiBudWxsOwoJCX0KCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI2dldFJvb3RNb2R1bGVzKElNb2R1bGUpCgkgKi8KCXB1YmxpYyBJTW9kdWxlW10gZ2V0Um9vdE1vZHVsZXMoSU1vZHVsZSBtb2R1bGUsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCWlmIChtb2R1bGUgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTW9kdWxlIGNhbm5vdCBiZSBudWxsIik7CgkJdHJ5IHsKCQkJcmV0dXJuIGdldERlbGVnYXRlKG1vbml0b3IpLmdldFJvb3RNb2R1bGVzKG1vZHVsZSk7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBzZSkgewoJCQkvL1RyYWNlLnRyYWNlKFRyYWNlLkZJTkVSLCAiQ29yZUV4Y2VwdGlvbiBjYWxsaW5nIGRlbGVnYXRlIGdldFBhcmVudE1vZHVsZXMoKSAiICsgdG9TdHJpbmcoKSArICI6ICIgKyBzZS5nZXRNZXNzYWdlKCkpOwoJCQl0aHJvdyBzZTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIGdldFBhcmVudE1vZHVsZXMoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXJldHVybiBudWxsOwoJCX0KCX0KCQoJLyoqCgkgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIGdpdmVuIG1vZHVsZSBjYW4gYmUgcmVzdGFydGVkLgoJICoKCSAqIEBwYXJhbSBtb2R1bGUgdGhlIG1vZHVsZQoJICogQHBhcmFtIG1vbml0b3IKCSAqIEByZXR1cm4gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIGdpdmVuIG1vZHVsZSBjYW4gYmUKCSAqICAgIHJlc3RhcnRlZCwgYW5kIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqLwoJcHVibGljIElTdGF0dXMgY2FuQ29udHJvbE1vZHVsZShJTW9kdWxlW10gbW9kdWxlLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlpZiAobW9kdWxlID09IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oIk1vZHVsZSBjYW5ub3QgYmUgbnVsbCIpOwoJCXRyeSB7CgkJCWJvb2xlYW4gYiA9IGdldEJlaGF2aW91ckRlbGVnYXRlKG1vbml0b3IpLmNhbkNvbnRyb2xNb2R1bGUobW9kdWxlKTsKCQkJaWYgKGIpCgkJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBNZXNzYWdlcy5jYW5SZXN0YXJ0TW9kdWxlT2ssIG51bGwpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgY2FuUmVzdGFydFJ1bnRpbWUoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJfQoJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yUmVzdGFydE1vZHVsZSwgbnVsbCk7Cgl9CgoJLyoqCgkgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gbW9kdWxlIGlzIGluIHN5bmMgb24gdGhlIHNlcnZlci4gSXQgc2hvdWxkCgkgKiByZXR1cm4gdHJ1ZSBpZiB0aGUgbW9kdWxlIHNob3VsZCBiZSByZXN0YXJ0ZWQgKGlzIG91dCBvZgoJICogc3luYykgb3IgZmFsc2UgaWYgdGhlIG1vZHVsZSBkb2VzIG5vdCBuZWVkIHRvIGJlIHJlc3RhcnRlZC4KCSAqCgkgKiBAcGFyYW0gbW9kdWxlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC5JTW9kdWxlCgkgKiBAcmV0dXJuIGJvb2xlYW4KCSAqLwoJcHVibGljIGJvb2xlYW4gZ2V0TW9kdWxlUmVzdGFydFN0YXRlKElNb2R1bGVbXSBtb2R1bGUpIHsKCQlpZiAobW9kdWxlID09IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oIk1vZHVsZSBjYW5ub3QgYmUgbnVsbCIpOwoJCXRyeSB7CgkJCUJvb2xlYW4gYiA9IChCb29sZWFuKSBtb2R1bGVSZXN0YXJ0U3RhdGUuZ2V0KGdldEtleShtb2R1bGUpKTsKCQkJaWYgKGIgIT0gbnVsbCkKCQkJCXJldHVybiBiLmJvb2xlYW5WYWx1ZSgpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCS8vIGlnbm9yZQoJCX0KCQlyZXR1cm4gZmFsc2U7Cgl9CgoJLyoKCSAqIEBzZWUgSVNlcnZlciNzdGFydE1vZHVsZShJTW9kdWxlW10sIElPcGVyYXRpb25MaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgc3RhcnRNb2R1bGUoSU1vZHVsZVtdIG1vZHVsZSwgSU9wZXJhdGlvbkxpc3RlbmVyIGxpc3RlbmVyKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJNb2R1bGUgY2Fubm90IGJlIG51bGwiKTsKCQl0cnkgewoJCQlnZXRCZWhhdmlvdXJEZWxlZ2F0ZShudWxsKS5zdGFydE1vZHVsZShtb2R1bGUsIG51bGwpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgcmVzdGFydE1vZHVsZSgpICIgKyB0b1N0cmluZygpLCBlKTsKCQl9Cgl9CgkKCS8qCgkgKiBAc2VlIElTZXJ2ZXIjc3RvcE1vZHVsZShJTW9kdWxlW10sIElPcGVyYXRpb25MaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgc3RvcE1vZHVsZShJTW9kdWxlW10gbW9kdWxlLCBJT3BlcmF0aW9uTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlpZiAobW9kdWxlID09IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oIk1vZHVsZSBjYW5ub3QgYmUgbnVsbCIpOwoJCXRyeSB7CgkJCWdldEJlaGF2aW91ckRlbGVnYXRlKG51bGwpLnN0b3BNb2R1bGUobW9kdWxlLCBudWxsKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIHJlc3RhcnRNb2R1bGUoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJfQoJfQoJCgkvKgoJICogQHNlZSBJU2VydmVyI3Jlc3RhcnRNb2R1bGUoSU1vZHVsZVtdLCBJT3BlcmF0aW9uTGlzdGVuZXIsIElQcm9ncmVzc01vbml0b3IpCgkgKi8KCXB1YmxpYyB2b2lkIHJlc3RhcnRNb2R1bGUoSU1vZHVsZVtdIG1vZHVsZSwgSU9wZXJhdGlvbkxpc3RlbmVyIGxpc3RlbmVyKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJNb2R1bGUgY2Fubm90IGJlIG51bGwiKTsKCQl0cnkgewoJCQlnZXRCZWhhdmlvdXJEZWxlZ2F0ZShudWxsKS5zdG9wTW9kdWxlKG1vZHVsZSwgbnVsbCk7CgkJCWdldEJlaGF2aW91ckRlbGVnYXRlKG51bGwpLnN0YXJ0TW9kdWxlKG1vZHVsZSwgbnVsbCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSByZXN0YXJ0TW9kdWxlKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCX0KCX0KCQoJLyoqCgkgKiBSZXR1cm5zIGFuIGFycmF5IG9mIElTZXJ2ZXJQb3J0cyB0aGF0IHRoaXMgc2VydmVyIGhhcy4KCSAqCgkgKiBAcGFyYW0gbW9uaXRvcgoJICogQHJldHVybiBhIHBvc3NpYmx5IGVtcHR5IGFycmF5IG9mIHNlcnZlcnMgcG9ydHMKCSAqLwoJcHVibGljIFNlcnZlclBvcnRbXSBnZXRTZXJ2ZXJQb3J0cyhJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQl0cnkgewoJCQlyZXR1cm4gZ2V0RGVsZWdhdGUobW9uaXRvcikuZ2V0U2VydmVyUG9ydHMoKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIGdldFNlcnZlclBvcnRzKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCQlyZXR1cm4gbnVsbDsKCQl9Cgl9CgkKCS8qKgoJICogVmlzaXQgYWxsIHRoZSBtb2R1bGVzIGluIHRoZSBzZXJ2ZXIgd2l0aCB0aGUgZ2l2ZW4gbW9kdWxlIHZpc2l0b3IuCgkgKiAKCSAqIEBwYXJhbSB2aXNpdG9yIHRoZSB2aXNpdG9yCgkgKiBAcGFyYW0gbW9uaXRvciBhIHByb2dyZXNzIG1vbml0b3IsIG9yIDxjb2RlPm51bGw8L2NvZGU+IGlmIHByb2dyZXNzCgkgKiAgICByZXBvcnRpbmcgYW5kIGNhbmNlbGxhdGlvbiBhcmUgbm90IGRlc2lyZWQKCSAqLwoJcHVibGljIHZvaWQgdmlzaXQoSU1vZHVsZVZpc2l0b3IgdmlzaXRvciwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKHZpc2l0b3IgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiVmlzaXRvciBjYW5ub3QgYmUgbnVsbCIpOwoJCUlNb2R1bGVbXSBtb2R1bGVzMiA9IGdldE1vZHVsZXMoKTsKCQlpZiAobW9kdWxlczIgIT0gbnVsbCkgeyAKCQkJaW50IHNpemUgPSBtb2R1bGVzMi5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlpZiAoIXZpc2l0TW9kdWxlKG5ldyBJTW9kdWxlW10geyBtb2R1bGVzMltpXSB9LCB2aXNpdG9yLCBtb25pdG9yKSkKCQkJCQlyZXR1cm47CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgdG8ga2VlcCB2aXNpdGluZywgYW5kIGZhbHNlIHRvIHN0b3AuCgkgKiAKCSAqIEBwYXJhbSBtb25pdG9yIGEgcHJvZ3Jlc3MgbW9uaXRvciwgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgcHJvZ3Jlc3MKCSAqICAgIHJlcG9ydGluZyBhbmQgY2FuY2VsbGF0aW9uIGFyZSBub3QgZGVzaXJlZAoJICovCglwcml2YXRlIGJvb2xlYW4gdmlzaXRNb2R1bGUoSU1vZHVsZVtdIG1vZHVsZSwgSU1vZHVsZVZpc2l0b3IgdmlzaXRvciwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQlyZXR1cm4gdHJ1ZTsKCQkKCQlpZiAoIXZpc2l0b3IudmlzaXQobW9kdWxlKSkKCQkJcmV0dXJuIGZhbHNlOwoJCQoJCUlNb2R1bGVbXSBjaGlsZHJlbiA9IGdldENoaWxkTW9kdWxlcyhtb2R1bGUsIG1vbml0b3IpOwoJCWlmIChjaGlsZHJlbiAhPSBudWxsKSB7CgkJCWludCBzaXplID0gY2hpbGRyZW4ubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJSU1vZHVsZVtdIG1vZHVsZTIgPSBuZXcgSU1vZHVsZVttb2R1bGUubGVuZ3RoICsgMV07CgkJCQlTeXN0ZW0uYXJyYXljb3B5KG1vZHVsZSwgMCwgbW9kdWxlMiwgMCwgbW9kdWxlLmxlbmd0aCk7CgkJCQltb2R1bGUyW21vZHVsZS5sZW5ndGhdID0gY2hpbGRyZW5baV07CgkJCQkKCQkJCWlmICghdmlzaXRNb2R1bGUobW9kdWxlMiwgdmlzaXRvciwgbW9uaXRvcikpCgkJCQkJcmV0dXJuIGZhbHNlOwoJCQl9CgkJfQoJCQoJCXJldHVybiB0cnVlOwoJfQoJCglwcml2YXRlIFN0cmluZyBnZXRLZXkoSU1vZHVsZVtdIG1vZHVsZSkgewoJCVN0cmluZ0J1ZmZlciBzYiA9IG5ldyBTdHJpbmdCdWZmZXIoKTsKCQkKCQlpZiAobW9kdWxlICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBtb2R1bGUubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGkgIT0gMCkKCQkJCQlzYi5hcHBlbmQoIiMiKTsKCQkJCXNiLmFwcGVuZChtb2R1bGVbaV0uZ2V0SWQoKSk7CgkJCX0KCQl9CgkJCgkJcmV0dXJuIHNiLnRvU3RyaW5nKCk7Cgl9CgkKCXB1YmxpYyB2b2lkIHNldE1vZHVsZVN0YXR1cyhJTW9kdWxlW10gbW9kdWxlLCBJU3RhdHVzIHN0YXR1cykgewoJCWlmIChtb2R1bGUgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTW9kdWxlIGNhbm5vdCBiZSBudWxsIik7CgkJbW9kdWxlU3RhdHVzLnB1dChnZXRLZXkobW9kdWxlKSwgc3RhdHVzKTsKCQkvL2ZpcmVTZXJ2ZXJNb2R1bGVTdGF0ZUNoYW5nZUV2ZW50KG1vZHVsZSk7Cgl9CgkKCXB1YmxpYyBJU3RhdHVzIGdldE1vZHVsZVN0YXR1cyhJTW9kdWxlW10gbW9kdWxlKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJNb2R1bGUgY2Fubm90IGJlIG51bGwiKTsKCQl0cnkgewoJCQlyZXR1cm4gKElTdGF0dXMpIG1vZHVsZVN0YXR1cy5nZXQoZ2V0S2V5KG1vZHVsZSkpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCXJldHVybiBudWxsOwoJCX0KCX0KCQoJcHVibGljIHZvaWQgc2V0U2VydmVyU3RhdHVzKElTdGF0dXMgc3RhdHVzKSB7CgkJc2VydmVyU3RhdHVzID0gc3RhdHVzOwoJCS8vZmlyZVNlcnZlclN0YXRlQ2hhbmdlRXZlbnQoKTsKCX0KCQoJcHVibGljIElTdGF0dXMgZ2V0U2VydmVyU3RhdHVzKCkgewoJCXJldHVybiBzZXJ2ZXJTdGF0dXM7Cgl9Cn0=