LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDExIElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuYWN0aW9uczsKCmltcG9ydCBqYXZhLnV0aWwuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRm9sZGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSVByb2plY3Q7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JUmVzb3VyY2U7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5qb2JzLkpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLmRlYnVnLmNvcmUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmRlYnVnLnVpLklEZWJ1Z1VJQ29uc3RhbnRzOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UuYWN0aW9uLklBY3Rpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS5kaWFsb2dzLkVycm9yRGlhbG9nOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2Uudmlld2Vycy5JU2VsZWN0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2Uudmlld2Vycy5JU3RydWN0dXJlZFNlbGVjdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLndpbmRvdy5XaW5kb3c7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS53aXphcmQuV2l6YXJkRGlhbG9nOwppbXBvcnQgb3JnLmVjbGlwc2Uub3NnaS51dGlsLk5MUzsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLkRpc3BsYXk7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5TaGVsbDsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLklXb3JrYmVuY2hXaW5kb3c7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5JV29ya2JlbmNoV2luZG93QWN0aW9uRGVsZWdhdGU7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5JQ2xpZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLklMYXVuY2hhYmxlQWRhcHRlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5TZXJ2ZXJQbHVnaW47CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLnVpLmludGVybmFsLlRyYWNlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLm1vZGVsLk1vZHVsZUFydGlmYWN0RGVsZWdhdGU7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLnVpLmludGVybmFsLio7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLnVpLmludGVybmFsLnZpZXdlcnMuTW9kdWxlQXJ0aWZhY3RDb21wb3NpdGU7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLnVpLmludGVybmFsLndpemFyZC5SdW5PblNlcnZlcldpemFyZDsKLyoqCiAqIFN1cHBvcnQgZm9yIHN0YXJ0aW5nL3N0b3BwaW5nIHNlcnZlciBhbmQgY2xpZW50cyBmb3IgcmVzb3VyY2VzIHJ1bm5pbmcgb24gYSBzZXJ2ZXIuCiAqLwpwdWJsaWMgY2xhc3MgUnVuT25TZXJ2ZXJBY3Rpb25EZWxlZ2F0ZSBpbXBsZW1lbnRzIElXb3JrYmVuY2hXaW5kb3dBY3Rpb25EZWxlZ2F0ZSB7Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZ1tdIGxhdW5jaE1vZGVzID0gewoJCUlMYXVuY2hNYW5hZ2VyLlJVTl9NT0RFLCBJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLCBJTGF1bmNoTWFuYWdlci5QUk9GSUxFX01PREUgfTsKCglwdWJsaWMgc3RhdGljIFN0cmluZyBST1NfQ0xJRU5UID0gInJvc19jbGllbnQiOwoJcHVibGljIHN0YXRpYyBTdHJpbmcgUk9TX0xBVU5DSEFCTEUgPSAicm9zX2xhdW5jaGFibGUiOwoJCglwcm90ZWN0ZWQgT2JqZWN0IHNlbGVjdGlvbjsKCglwcm90ZWN0ZWQgSVdvcmtiZW5jaFdpbmRvdyB3aW5kb3c7CgoJcHJvdGVjdGVkIHN0YXRpYyBPYmplY3QgZ2xvYmFsU2VsZWN0aW9uOwoKCXByb3RlY3RlZCBzdGF0aWMgTWFwPFN0cmluZywgQm9vbGVhbj4gZ2xvYmFsTGF1bmNoTW9kZTsKCXByb3RlY3RlZCBTdHJpbmcgbGF1bmNoTW9kZSA9IElMYXVuY2hNYW5hZ2VyLlJVTl9NT0RFOwoKCXByb3RlY3RlZCBib29sZWFuIHRhc2tzQW5kQ2xpZW50U2hvd247CgkKCXByb3RlY3RlZCBIYXNoTWFwPFN0cmluZywgT2JqZWN0PiB3aXpfcHJvcGVydGllczsgCgoJcHJvdGVjdGVkIElMYXVuY2hhYmxlQWRhcHRlciBsYXVuY2hhYmxlQWRhcHRlcjsKCXByb3RlY3RlZCBJQ2xpZW50IGNsaWVudDsKCgkvKioKCSAqIFJ1bk9uU2VydmVyQWN0aW9uRGVsZWdhdGUgY29uc3RydWN0b3IgY29tbWVudC4KCSAqLwoJcHVibGljIFJ1bk9uU2VydmVyQWN0aW9uRGVsZWdhdGUoKSB7CgkJc3VwZXIoKTsKCX0KCQoJLyoqCgkgKiBSdW5PblNlcnZlckFjdGlvbkRlbGVnYXRlIGNvbnN0cnVjdG9yIGNvbW1lbnQuCgkgKi8KCXB1YmxpYyBSdW5PblNlcnZlckFjdGlvbkRlbGVnYXRlKEhhc2hNYXA8U3RyaW5nLCBPYmplY3Q+cHJvcGVydGllcykgewoJCXRoaXMud2l6X3Byb3BlcnRpZXMgPSBwcm9wZXJ0aWVzOwoJfQoJCglwdWJsaWMgdm9pZCBzZXRBY3Rpb25Qcm9wZXJ0aWVzKEhhc2hNYXA8U3RyaW5nLE9iamVjdD5wcm9wZXJ0aWVzKXsKCQl0aGlzLndpel9wcm9wZXJ0aWVzID0gcHJvcGVydGllczsKCX0KCgkvKioKCSAqIERpc3Bvc2VzIHRoaXMgYWN0aW9uIGRlbGVnYXRlLiAgVGhlIGltcGxlbWVudG9yIHNob3VsZCB1bmhvb2sgYW55IHJlZmVyZW5jZXMKCSAqIHRvIGl0c2VsZiBzbyB0aGF0IGdhcmJhZ2UgY29sbGVjdGlvbiBjYW4gb2NjdXIuCgkgKi8KCXB1YmxpYyB2b2lkIGRpc3Bvc2UoKSB7CgkJd2luZG93ID0gbnVsbDsKCX0KCgkvKioKCSAqIEluaXRpYWxpemVzIHRoaXMgYWN0aW9uIGRlbGVnYXRlIHdpdGggdGhlIHdvcmtiZW5jaCB3aW5kb3cgaXQgd2lsbCB3b3JrIGluLgoJICoKCSAqIEBwYXJhbSBuZXdXaW5kb3cgdGhlIHdpbmRvdyB0aGF0IHByb3ZpZGVzIHRoZSBjb250ZXh0IGZvciB0aGlzIGRlbGVnYXRlCgkgKi8KCXB1YmxpYyB2b2lkIGluaXQoSVdvcmtiZW5jaFdpbmRvdyBuZXdXaW5kb3cpIHsKCQl3aW5kb3cgPSBuZXdXaW5kb3c7Cgl9CgoJcHVibGljIElTZXJ2ZXIgZ2V0U2VydmVyKElNb2R1bGUgbW9kdWxlLCBJTW9kdWxlQXJ0aWZhY3QgbW9kdWxlQXJ0aWZhY3QsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUlTZXJ2ZXIgc2VydmVyID0gU2VydmVyQ29yZS5nZXREZWZhdWx0U2VydmVyKG1vZHVsZSk7CgkJCgkJLy8gaWdub3JlIHByZWZlcmVuY2UgaWYgdGhlIHNlcnZlciBkb2Vzbid0IHN1cHBvcnQgdGhpcyBtb2RlLgoJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiAhU2VydmVyVUlQbHVnaW4uaXNDb21wYXRpYmxlV2l0aExhdW5jaE1vZGUoc2VydmVyLCBsYXVuY2hNb2RlKSkKCQkJc2VydmVyID0gbnVsbDsKCQkKCQlpZiAoc2VydmVyICE9IG51bGwgJiYgIVNlcnZlclV0aWwuY29udGFpbnNNb2R1bGUoc2VydmVyLCBtb2R1bGUsIG1vbml0b3IpKSB7CgkJCUlTZXJ2ZXJXb3JraW5nQ29weSB3YyA9IHNlcnZlci5jcmVhdGVXb3JraW5nQ29weSgpOwoJCQl0cnkgewoJCQkJU2VydmVyVXRpbC5tb2RpZnlNb2R1bGVzKHdjLCBuZXcgSU1vZHVsZVtdIHsgbW9kdWxlIH0sIG5ldyBJTW9kdWxlWzBdLCBtb25pdG9yKTsKCQkJCXdjLnNhdmUoZmFsc2UsIG1vbml0b3IpOwoJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCQlpZiAoVHJhY2UuU0VWRVJFKSB7CgkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU1RSSU5HX1NFVkVSRSwgIkNvdWxkIG5vdCBhZGQgbW9kdWxlIHRvIHNlcnZlciIsIGNlKTsKCQkJCX0KCQkJCXNlcnZlciA9IG51bGw7CgkJCX0KCQl9CgkJCgkJU2hlbGwgc2hlbGw7CgkJaWYgKHdpbmRvdyAhPSBudWxsKQoJCQlzaGVsbCA9IHdpbmRvdy5nZXRTaGVsbCgpOwoJCWVsc2UKCQkJc2hlbGwgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRJbnN0YW5jZSgpLmdldFdvcmtiZW5jaCgpLmdldEFjdGl2ZVdvcmtiZW5jaFdpbmRvdygpLmdldFNoZWxsKCk7CgkJCgkJaWYgKHNlcnZlciA9PSBudWxsKSB7CgkJCS8vIHRyeSB0aGUgZnVsbCB3aXphcmQKCQkJaWYgKFRyYWNlLkZJTkVTVCkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU1RSSU5HX0ZJTkVTVCwgIkxhdW5jaGluZyB3aXphcmQiKTsKCQkJfQoJCQlSdW5PblNlcnZlcldpemFyZCB3aXphcmQgPSBuZXcgUnVuT25TZXJ2ZXJXaXphcmQobW9kdWxlLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCwgd2l6X3Byb3BlcnRpZXMpOwoKCQkJV2l6YXJkRGlhbG9nIGRpYWxvZyA9IG5ldyBXaXphcmREaWFsb2coc2hlbGwsIHdpemFyZCk7CgkJCWlmIChkaWFsb2cub3BlbigpID09IFdpbmRvdy5DQU5DRUwpIHsKCQkJCWlmIChtb25pdG9yICE9IG51bGwpCgkJCQkJbW9uaXRvci5zZXRDYW5jZWxlZCh0cnVlKTsKCQkJCXJldHVybiBudWxsOwoJCQl9CgkJCQoJCQl0cnkgewoJCQkJSm9iLmdldEpvYk1hbmFnZXIoKS5qb2luKCJvcmcuZWNsaXBzZS53c3Quc2VydmVyLnVpLmZhbWlseSIsIG51bGwpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJaWYgKFRyYWNlLldBUk5JTkcpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfV0FSTklORywgIkVycm9yIHdhaXRpbmcgZm9yIGpvYiIsIGUpOwoJCQkJfQoJCQl9CgkJCXNlcnZlciA9IHdpemFyZC5nZXRTZXJ2ZXIoKTsKCQkJYm9vbGVhbiBwcmVmZXJyZWQgPSB3aXphcmQuaXNQcmVmZXJyZWRTZXJ2ZXIoKTsKCQkJdGFza3NBbmRDbGllbnRTaG93biA9IHRydWU7CgkJCWlmIChjbGllbnQgPT0gbnVsbCB8fCBsYXVuY2hhYmxlQWRhcHRlciA9PSBudWxsKXsKCQkJCWNsaWVudCA9IHdpemFyZC5nZXRTZWxlY3RlZENsaWVudCgpOwoJCQkJbGF1bmNoYWJsZUFkYXB0ZXIgPSB3aXphcmQuZ2V0TGF1bmNoYWJsZUFkYXB0ZXIoKTsKCQkJfQoJCQkKCQkJLy8gc2V0IHByZWZlcnJlZCBzZXJ2ZXIgaWYgcmVxdWVzdGVkCgkJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiBwcmVmZXJyZWQpIHsKCQkJCXRyeSB7CgkJCQkJU2VydmVyQ29yZS5zZXREZWZhdWx0U2VydmVyKG1vZHVsZSwgc2VydmVyLCBtb25pdG9yKTsKCQkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJCQlTdHJpbmcgbWVzc2FnZSA9IE1lc3NhZ2VzLmVycm9yQ291bGROb3RTYXZlUHJlZmVyZW5jZTsKCQkJCQlFcnJvckRpYWxvZy5vcGVuRXJyb3Ioc2hlbGwsIE1lc3NhZ2VzLmVycm9yRGlhbG9nVGl0bGUsIG1lc3NhZ2UsIGNlLmdldFN0YXR1cygpKTsKCQkJCX0KCQkJfQoJCX0KCQkKCQl0cnkgewoJCQlKb2IuZ2V0Sm9iTWFuYWdlcigpLmpvaW4oIm9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuZmFtaWx5IiwgbmV3IE51bGxQcm9ncmVzc01vbml0b3IoKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJaWYgKFRyYWNlLldBUk5JTkcpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNUUklOR19XQVJOSU5HLCAiRXJyb3Igd2FpdGluZyBmb3Igam9iIiwgZSk7CgkJCX0KCQl9CgkJCgkJcmV0dXJuIHNlcnZlcjsKCX0KCgkvKioKCSAqIFJ1biB0aGUgcmVzb3VyY2Ugb24gYSBzZXJ2ZXIuCgkgKi8KCXByb3RlY3RlZCB2b2lkIHJ1bigpIHsKCQlmaW5hbCBJTW9kdWxlQXJ0aWZhY3RbXSBtb2R1bGVBcnRpZmFjdHMgPSBTZXJ2ZXJQbHVnaW4uZ2V0TW9kdWxlQXJ0aWZhY3RzKHNlbGVjdGlvbik7CgkJaWYgKG1vZHVsZUFydGlmYWN0cyA9PSBudWxsIHx8IG1vZHVsZUFydGlmYWN0cy5sZW5ndGggPT0gMCB8fCBtb2R1bGVBcnRpZmFjdHNbMF0gPT0gbnVsbCkgewoJCQlFY2xpcHNlVXRpbC5vcGVuRXJyb3IoTWVzc2FnZXMuZXJyb3JOb0FydGlmYWN0KTsKCQkJaWYgKFRyYWNlLkZJTkVTVCkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU1RSSU5HX0ZJTkVTVCwgIk5vIG1vZHVsZSBhcnRpZmFjdCBmb3VuZCIpOwoJCQl9CgkJCXJldHVybjsKCQl9CgkJCgkJU2hlbGwgc2hlbGwyID0gbnVsbDsKCQlpZiAod2luZG93ICE9IG51bGwpCgkJCXNoZWxsMiA9IHdpbmRvdy5nZXRTaGVsbCgpOwoJCWVsc2UgewoJCQl0cnkgewoJCQkJc2hlbGwyID0gU2VydmVyVUlQbHVnaW4uZ2V0SW5zdGFuY2UoKS5nZXRXb3JrYmVuY2goKS5nZXRBY3RpdmVXb3JrYmVuY2hXaW5kb3coKS5nZXRTaGVsbCgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJLy8gaWdub3JlCgkJCX0KCQkJaWYgKHNoZWxsMiA9PSBudWxsKQoJCQkJc2hlbGwyID0gRGlzcGxheS5nZXREZWZhdWx0KCkuZ2V0QWN0aXZlU2hlbGwoKTsKCQl9CgkJZmluYWwgU2hlbGwgc2hlbGwgPSBzaGVsbDI7CgkJZmluYWwgSUFkYXB0YWJsZSBpbmZvID0gbmV3IElBZGFwdGFibGUoKSB7CgkJCXB1YmxpYyBPYmplY3QgZ2V0QWRhcHRlcihDbGFzcyBhZGFwdGVyKSB7CgkJCQlpZiAoU2hlbGwuY2xhc3MuZXF1YWxzKGFkYXB0ZXIpKQoJCQkJCXJldHVybiBzaGVsbDsKCQkJCXJldHVybiBudWxsOwoJCQl9CgkJfTsKCQkKCQkvLyBJZiB0aGVyZSBpcyBtb3JlIHRoYW4gMSBtb2R1bGVBcnRpZmFjdCwgZ2V0IGEgdmFsaWQgTW9kdWxlQXJ0aWZhY3QgdGhhdCB3ZSBjYW4gdXNlIGZvciBsYXVuY2hpbmcKCQkvLyBUT0RPIFRoZSBNb2R1bGVBcnRpZmFjdENvbXBvc2l0ZSBzaG91bGQgYmUgcGFydCBvZiB0aGUgUnVuT25TZXJ2ZXJXaXphcmQKCQlmaW5hbCBJTW9kdWxlQXJ0aWZhY3QgbW9kdWxlQXJ0aWZhY3Q7CgkJaWYgKG1vZHVsZUFydGlmYWN0cy5sZW5ndGggPiAxKSB7CgkJCU1vZHVsZUFydGlmYWN0Q29tcG9zaXRlIGFydGlmYWN0Q29tcG9zaXRlID0gbmV3IE1vZHVsZUFydGlmYWN0Q29tcG9zaXRlKHNoZWxsLCBtb2R1bGVBcnRpZmFjdHMsIGxhdW5jaE1vZGUpOwoJCQlpZiAoYXJ0aWZhY3RDb21wb3NpdGUub3BlbigpID09IFdpbmRvdy5DQU5DRUwpCgkJCQlyZXR1cm47CgkJCQoJCQltb2R1bGVBcnRpZmFjdCA9IGFydGlmYWN0Q29tcG9zaXRlLmdldFNlbGVjdGlvbigpOwoJCX0gZWxzZQoJCQltb2R1bGVBcnRpZmFjdCA9IG1vZHVsZUFydGlmYWN0c1swXTsKCQkKCQlpZiAobW9kdWxlQXJ0aWZhY3QuZ2V0TW9kdWxlKCkgPT0gbnVsbCkgeyAvLyAxNDk0MjUKCQkJRWNsaXBzZVV0aWwub3BlbkVycm9yKE1lc3NhZ2VzLmVycm9yTm9Nb2R1bGVzKTsKCQkJaWYgKFRyYWNlLkZJTkVTVCkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU1RSSU5HX0ZJTkVTVCwgIk1vZHVsZSBhcnRpZmFjdCBub3QgY29udGFpbmVkIGluIGEgbW9kdWxlIik7CgkJCX0KCQkJcmV0dXJuOwoJCX0KCQlmaW5hbCBJTW9kdWxlIG1vZHVsZSA9IG1vZHVsZUFydGlmYWN0LmdldE1vZHVsZSgpOwoJCQoJCS8vIGNoZWNrIGZvciBzZXJ2ZXJzIHdpdGggdGhlIGdpdmVuIHN0YXJ0IG1vZGUKCQlJU2VydmVyW10gc2VydmVycyA9IFNlcnZlckNvcmUuZ2V0U2VydmVycygpOwoJCWJvb2xlYW4gZm91bmQgPSBmYWxzZTsKCQlpZiAoc2VydmVycyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gc2VydmVycy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZSAmJiAhZm91bmQ7IGkrKykgewoJCQkJaWYgKFNlcnZlclVJUGx1Z2luLmlzQ29tcGF0aWJsZVdpdGhMYXVuY2hNb2RlKHNlcnZlcnNbaV0sIGxhdW5jaE1vZGUpKSB7CgkJCQkJdHJ5IHsKCQkJCQkJSU1vZHVsZVtdIHBhcmVudHMgPSBzZXJ2ZXJzW2ldLmdldFJvb3RNb2R1bGVzKG1vZHVsZSwgbnVsbCk7CgkJCQkJCWlmIChwYXJlbnRzICE9IG51bGwgJiYgcGFyZW50cy5sZW5ndGggPiAwKQoJCQkJCQkJZm91bmQgPSB0cnVlOwoJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCS8vIGlnbm9yZQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQkKCQlpZiAoIWZvdW5kKSB7CgkJCS8vIG5vIGV4aXN0aW5nIHNlcnZlciBzdXBwb3J0cyB0aGUgcHJvamVjdCBhbmQgc3RhcnQgbW9kZSEKCQkJLy8gY2hlY2sgaWYgdGhlcmUgbWlnaHQgYmUgYW5vdGhlciBvbmUgdGhhdCBjYW4gYmUgY3JlYXRlZAoJCQlJU2VydmVyVHlwZVtdIHNlcnZlclR5cGVzID0gU2VydmVyQ29yZS5nZXRTZXJ2ZXJUeXBlcygpOwoJCQlpZiAoc2VydmVyVHlwZXMgIT0gbnVsbCkgewoJCQkJaW50IHNpemUgPSBzZXJ2ZXJUeXBlcy5sZW5ndGg7CgkJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemUgJiYgIWZvdW5kOyBpKyspIHsKCQkJCQlJU2VydmVyVHlwZSB0eXBlID0gc2VydmVyVHlwZXNbaV07CgkJCQkJSU1vZHVsZVR5cGVbXSBtb2R1bGVUeXBlcyA9IHR5cGUuZ2V0UnVudGltZVR5cGUoKS5nZXRNb2R1bGVUeXBlcygpOwoJCQkJCWlmICh0eXBlLnN1cHBvcnRzTGF1bmNoTW9kZShsYXVuY2hNb2RlKSAmJiBTZXJ2ZXJVdGlsLmlzU3VwcG9ydGVkTW9kdWxlKG1vZHVsZVR5cGVzLCBtb2R1bGUuZ2V0TW9kdWxlVHlwZSgpKSkgewoJCQkJCQlmb3VuZCA9IHRydWU7CgkJCQkJfQoJCQkJfQoJCQl9CgkJCWlmICghZm91bmQpIHsKCQkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihNZXNzYWdlcy5lcnJvck5vU2VydmVyKTsKCQkJCWlmIChUcmFjZS5GSU5FU1QpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfRklORVNULCAiTm8gc2VydmVyIGZvciBzdGFydCBtb2RlIik7CgkJCQl9CgkJCQlyZXR1cm47CgkJCX0KCQl9CgkJCgkJaWYgKCFTZXJ2ZXJVSVBsdWdpbi5zYXZlRWRpdG9ycygpKQoJCQlyZXR1cm47CgoJCXRhc2tzQW5kQ2xpZW50U2hvd24gPSBmYWxzZTsKCQlJU2VydmVyIHNlcnZlcjIgPSBudWxsOwoJCS8vIGluaXRpYWxpemUgaXRzIHZhbHVlIHVzaW5nIHRoZSBwcmVkZWZpbmVkIHZhbHVlIGlmIG9uZSBoYXMgYmVlbiBnaXZlbgoJCWNsaWVudCA9IChJQ2xpZW50KWdldE92ZXJ3cml0ZVZhbHVlKFJPU19DTElFTlQpOwoJCWxhdW5jaGFibGVBZGFwdGVyID0gKElMYXVuY2hhYmxlQWRhcHRlcikgZ2V0T3ZlcndyaXRlVmFsdWUoUk9TX0xBVU5DSEFCTEUpOwoJCQoJCXRyeSB7CgkJCUlQcm9ncmVzc01vbml0b3IgbW9uaXRvciA9IG5ldyBOdWxsUHJvZ3Jlc3NNb25pdG9yKCk7CgkJCXNlcnZlcjIgPSBnZXRTZXJ2ZXIobW9kdWxlLCBtb2R1bGVBcnRpZmFjdCwgbW9uaXRvcik7CgkJCWlmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkJCXJldHVybjsKCQkJCgkJCWlmIChzZXJ2ZXIyICE9IG51bGwpIHsKCQkJCUlGb2xkZXIgZm9sZGVyID0gc2VydmVyMi5nZXRTZXJ2ZXJDb25maWd1cmF0aW9uKCk7CgkJCQlpZiAoZm9sZGVyICE9IG51bGwgJiYgZm9sZGVyLmdldFByb2plY3QoKSAhPSBudWxsICYmICFmb2xkZXIuZ2V0UHJvamVjdCgpLmlzT3BlbigpKQoJCQkJCWZvbGRlci5nZXRQcm9qZWN0KCkub3Blbihtb25pdG9yKTsKCQkJfQoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJRWNsaXBzZVV0aWwub3BlbkVycm9yKHNoZWxsLCBjZS5nZXRMb2NhbGl6ZWRNZXNzYWdlKCkpOwoJCQlyZXR1cm47CgkJfQoJCWZpbmFsIElTZXJ2ZXIgc2VydmVyID0gc2VydmVyMjsKCQkvL2lmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkvLwlyZXR1cm47CgkJCgkJaWYgKFRyYWNlLkZJTkVTVCkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfRklORVNULCAiU2VydmVyOiAiICsgc2VydmVyKTsKCQl9CgkJCgkJaWYgKHNlcnZlciA9PSBudWxsKSB7CgkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihNZXNzYWdlcy5lcnJvck5vU2VydmVyKTsKCQkJaWYgKFRyYWNlLlNFVkVSRSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU1RSSU5HX1NFVkVSRSwgIk5vIHNlcnZlciBmb3VuZCIpOwoJCQl9CgkJCXJldHVybjsKCQl9CgkJCgkJaWYgKCFTZXJ2ZXJVSVBsdWdpbi5wcm9tcHRJZkRpcnR5KHNoZWxsLCBzZXJ2ZXIpKQoJCQlyZXR1cm47CgkJCgkJLy8gV2UgbmVlZCB0byBjaGVjayBpZiB0aGUgY2xpZW50IGFuZCBsYXVuY2hhYmxlIHdlcmUgcHJlLXBvcHVsYXRlZAoJCWlmICghdGFza3NBbmRDbGllbnRTaG93bikgewoJCQlSdW5PblNlcnZlcldpemFyZCB3aXphcmQgPSBuZXcgUnVuT25TZXJ2ZXJXaXphcmQoc2VydmVyLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCwgd2l6X3Byb3BlcnRpZXMpOwoJCQlpZiAod2l6YXJkLnNob3VsZEFwcGVhcigpKSB7CgkJCQlXaXphcmREaWFsb2cgZGlhbG9nID0gbmV3IFdpemFyZERpYWxvZyhzaGVsbCwgd2l6YXJkKTsKCQkJCWlmIChkaWFsb2cub3BlbigpID09IFdpbmRvdy5DQU5DRUwpCgkJCQkJcmV0dXJuOwoJCQl9IGVsc2UKCQkJCXdpemFyZC5wZXJmb3JtRmluaXNoKCk7CgkJCWNsaWVudCA9IHdpemFyZC5nZXRTZWxlY3RlZENsaWVudCgpOwoJCQlsYXVuY2hhYmxlQWRhcHRlciA9IHdpemFyZC5nZXRMYXVuY2hhYmxlQWRhcHRlcigpOwoJCX0KCQkKCQkvLyBpZiB0aGVyZSBpcyBubyBjbGllbnQsIHVzZSBhIGR1bW15CgkJaWYgKGNsaWVudCA9PSBudWxsKSB7CQkKCQkJY2xpZW50ID0gbmV3IElDbGllbnQoKSB7CgkJCQlwdWJsaWMgU3RyaW5nIGdldERlc2NyaXB0aW9uKCkgewoJCQkJCXJldHVybiBNZXNzYWdlcy5jbGllbnREZWZhdWx0RGVzY3JpcHRpb247CgkJCQl9CgoJCQkJcHVibGljIFN0cmluZyBnZXRJZCgpIHsKCQkJCQlyZXR1cm4gIm9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuY2xpZW50LmRlZmF1bHQiOwoJCQkJfQoKCQkJCXB1YmxpYyBTdHJpbmcgZ2V0TmFtZSgpIHsKCQkJCQlyZXR1cm4gTWVzc2FnZXMuY2xpZW50RGVmYXVsdE5hbWU7CgkJCQl9CgoJCQkJcHVibGljIElTdGF0dXMgbGF1bmNoKElTZXJ2ZXIgc2VydmVyMywgT2JqZWN0IGxhdW5jaGFibGUyLCBTdHJpbmcgbGF1bmNoTW9kZTMsIElMYXVuY2ggbGF1bmNoKSB7CgkJCQkJcmV0dXJuIFN0YXR1cy5PS19TVEFUVVM7CgkJCQl9CgoJCQkJcHVibGljIGJvb2xlYW4gc3VwcG9ydHMoSVNlcnZlciBzZXJ2ZXIzLCBPYmplY3QgbGF1bmNoYWJsZTIsIFN0cmluZyBsYXVuY2hNb2RlMykgewoJCQkJCXJldHVybiB0cnVlOwoJCQkJfQoJCQl9OwoJCX0KCQkKCQlpZiAobW9kdWxlQXJ0aWZhY3QgaW5zdGFuY2VvZiBNb2R1bGVBcnRpZmFjdERlbGVnYXRlKSB7CgkJCWJvb2xlYW4gY2FuTG9hZCA9IGZhbHNlOwoJCQl0cnkgewoJCQkJQ2xhc3MgYyA9IENsYXNzLmZvck5hbWUobW9kdWxlQXJ0aWZhY3QuZ2V0Q2xhc3MoKS5nZXROYW1lKCkpOwoJCQkJaWYgKGMubmV3SW5zdGFuY2UoKSAhPSBudWxsKQoJCQkJCWNhbkxvYWQgPSB0cnVlOwoJCQl9IGNhdGNoIChUaHJvd2FibGUgdCkgewoJCQkJaWYgKFRyYWNlLldBUk5JTkcpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfV0FSTklORywKCQkJCQkJCSJDb3VsZCBub3QgbG9hZCBtb2R1bGUgYXJ0aWZhY3QgZGVsZWdhdGUgY2xhc3MsIHN3aXRjaGluZyB0byBiYWNrdXAiKTsKCQkJCX0KCQkJfQoJCQlpZiAoY2FuTG9hZCkgewoJCQkJdHJ5IHsKCQkJCQlJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IgPSBuZXcgTnVsbFByb2dyZXNzTW9uaXRvcigpOwoJCQkJCUlMYXVuY2hDb25maWd1cmF0aW9uIGNvbmZpZyA9IGdldExhdW5jaENvbmZpZ3VyYXRpb24oc2VydmVyLCAoTW9kdWxlQXJ0aWZhY3REZWxlZ2F0ZSkgbW9kdWxlQXJ0aWZhY3QsIGxhdW5jaGFibGVBZGFwdGVyLCBjbGllbnQsIG1vbml0b3IpOwoJCQkJCWNvbmZpZy5sYXVuY2gobGF1bmNoTW9kZSwgbW9uaXRvcik7CgkJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCQkJaWYgKFRyYWNlLlNFVkVSRSkgewoJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfU0VWRVJFLCAiQ291bGQgbm90IGxhdW5jaCBSdW4gb24gU2VydmVyIiwgY2UpOwoJCQkJCX0KCQkJCX0KCQkJCXJldHVybjsKCQkJfQoJCX0KCQkKCQlUaHJlYWQgdGhyZWFkID0gbmV3IFRocmVhZCgiUnVuIG9uIFNlcnZlciIpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJaWYgKFRyYWNlLkZJTkVTVCkgewoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNUUklOR19GSU5FU1QsICJSZWFkeSB0byBsYXVuY2giKTsKCQkJCX0KCQkJCQoJCQkJLy8gc3RhcnQgc2VydmVyIGlmIGl0J3Mgbm90IGFscmVhZHkgc3RhcnRlZAoJCQkJLy8gYW5kIGN1ZSB0aGUgY2xpZW50IHRvIHN0YXJ0CgkJCQlJTW9kdWxlW10gbW9kdWxlcyA9IG5ldyBJTW9kdWxlW10geyBtb2R1bGUgfTsgLy8gVE9ETzogZ2V0IHBhcmVudCBoaWVyYXJjaHkgY29ycmVjdAoJCQkJaW50IHN0YXRlID0gc2VydmVyLmdldFNlcnZlclN0YXRlKCk7CgkJCQlpZiAoc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVEFSVElORykgewoJCQkJCUxhdW5jaENsaWVudEpvYiBjbGllbnRKb2IgPSBuZXcgTGF1bmNoQ2xpZW50Sm9iKHNlcnZlciwgbW9kdWxlcywgbGF1bmNoTW9kZSwgbW9kdWxlQXJ0aWZhY3QsIGxhdW5jaGFibGVBZGFwdGVyLCBjbGllbnQpOwoJCQkJCWNsaWVudEpvYi5zY2hlZHVsZSgpOwoJCQkJfSBlbHNlIGlmIChzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQpIHsKCQkJCQlib29sZWFuIHJlc3RhcnQgPSBmYWxzZTsKCQkJCQlTdHJpbmcgbW9kZSA9IHNlcnZlci5nZXRNb2RlKCk7CgkJCQkJSUJyZWFrcG9pbnRNYW5hZ2VyIGJyZWFrcG9pbnRNYW5hZ2VyID0gRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldEJyZWFrcG9pbnRNYW5hZ2VyKCk7CgkJCQkJYm9vbGVhbiBkaXNhYmxlZEJyZWFrcG9pbnRzID0gZmFsc2U7CgkJCQkJCgkJCQkJaWYgKHNlcnZlci5nZXRTZXJ2ZXJSZXN0YXJ0U3RhdGUoKSkgewoJCQkJCQlpbnQgcmVzdWx0ID0gb3BlblJlc3RhcnREaWFsb2coc2hlbGwpOwoJCQkJCQlpZiAocmVzdWx0ID09IDApIHsKCQkJCQkJCWxhdW5jaE1vZGUgPSBtb2RlOwoJCQkJCQkJcmVzdGFydCA9IHRydWU7CgkJCQkJCX0gZWxzZSBpZiAocmVzdWx0ID09IDkpIC8vIGNhbmNlbAoJCQkJCQkJcmV0dXJuOwoJCQkJCX0KCQkJCQlpZiAoIXJlc3RhcnQpIHsKCQkJCQkJaWYgKCFJTGF1bmNoTWFuYWdlci5SVU5fTU9ERS5lcXVhbHMobW9kZSkgJiYgSUxhdW5jaE1hbmFnZXIuUlVOX01PREUuZXF1YWxzKGxhdW5jaE1vZGUpKSB7CgkJCQkJCQlib29sZWFuIGJyZWFrcG9pbnRzT3B0aW9uID0gZmFsc2U7CgkJCQkJCQlpZiAoYnJlYWtwb2ludE1hbmFnZXIuaXNFbmFibGVkKCkgJiYgSUxhdW5jaE1hbmFnZXIuREVCVUdfTU9ERS5lcXVhbHMobW9kZSkpCgkJCQkJCQkJYnJlYWtwb2ludHNPcHRpb24gPSB0cnVlOwoJCQkJCQkJaW50IHJlc3VsdCA9IG9wZW5PcHRpb25zRGlhbG9nKHNoZWxsLCBNZXNzYWdlcy53aXpSdW5PblNlcnZlclRpdGxlLCBNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ1J1biwgYnJlYWtwb2ludHNPcHRpb24pOwoJCQkJCQkJaWYgKHJlc3VsdCA9PSAwKQoJCQkJCQkJCXJlc3RhcnQgPSB0cnVlOwoJCQkJCQkJZWxzZSBpZiAocmVzdWx0ID09IDEpIHsKCQkJCQkJCQlicmVha3BvaW50TWFuYWdlci5zZXRFbmFibGVkKGZhbHNlKTsKCQkJCQkJCQlkaXNhYmxlZEJyZWFrcG9pbnRzID0gdHJ1ZTsKCQkJCQkJCQlsYXVuY2hNb2RlID0gbW9kZTsKCQkJCQkJCX0gZWxzZSBpZiAocmVzdWx0ID09IDIpCgkJCQkJCQkJbGF1bmNoTW9kZSA9IG1vZGU7CgkJCQkJCQllbHNlIC8vIHJlc3VsdCA9PSA5IC8vIGNhbmNlbAoJCQkJCQkJCXJldHVybjsKCQkJCQkJfSBlbHNlIGlmICghSUxhdW5jaE1hbmFnZXIuREVCVUdfTU9ERS5lcXVhbHMobW9kZSkgJiYgSUxhdW5jaE1hbmFnZXIuREVCVUdfTU9ERS5lcXVhbHMobGF1bmNoTW9kZSkpIHsKCQkJCQkJCWludCByZXN1bHQgPSBvcGVuT3B0aW9uc0RpYWxvZyhzaGVsbCwgTWVzc2FnZXMud2l6RGVidWdPblNlcnZlclRpdGxlLCBNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0RlYnVnLCBmYWxzZSk7CgkJCQkJCQlpZiAocmVzdWx0ID09IDApCgkJCQkJCQkJcmVzdGFydCA9IHRydWU7CgkJCQkJCQllbHNlIGlmIChyZXN1bHQgPT0gMSkKCQkJCQkJCQlsYXVuY2hNb2RlID0gbW9kZTsKCQkJCQkJCWVsc2UgLy8gcmVzdWx0ID09IDkgLy8gY2FuY2VsCgkJCQkJCQkJcmV0dXJuOwoJCQkJCQl9IGVsc2UgaWYgKCFJTGF1bmNoTWFuYWdlci5QUk9GSUxFX01PREUuZXF1YWxzKG1vZGUpICYmIElMYXVuY2hNYW5hZ2VyLlBST0ZJTEVfTU9ERS5lcXVhbHMobGF1bmNoTW9kZSkpIHsKCQkJCQkJCWJvb2xlYW4gYnJlYWtwb2ludHNPcHRpb24gPSBmYWxzZTsKCQkJCQkJCWlmIChicmVha3BvaW50TWFuYWdlci5pc0VuYWJsZWQoKSAmJiBJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLmVxdWFscyhtb2RlKSkKCQkJCQkJCQlicmVha3BvaW50c09wdGlvbiA9IHRydWU7CgkJCQkJCQlpbnQgcmVzdWx0ID0gb3Blbk9wdGlvbnNEaWFsb2coc2hlbGwsIE1lc3NhZ2VzLndpelByb2ZpbGVPblNlcnZlclRpdGxlLCBNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ1Byb2ZpbGUsIGJyZWFrcG9pbnRzT3B0aW9uKTsKCQkJCQkJCWlmIChyZXN1bHQgPT0gMCkKCQkJCQkJCQlyZXN0YXJ0ID0gdHJ1ZTsKCQkJCQkJCWVsc2UgaWYgKHJlc3VsdCA9PSAxKSB7CgkJCQkJCQkJYnJlYWtwb2ludE1hbmFnZXIuc2V0RW5hYmxlZChmYWxzZSk7CgkJCQkJCQkJZGlzYWJsZWRCcmVha3BvaW50cyA9IHRydWU7CgkJCQkJCQkJbGF1bmNoTW9kZSA9IG1vZGU7CgkJCQkJCQl9IGVsc2UgaWYgKHJlc3VsdCA9PSAyKQoJCQkJCQkJCWxhdW5jaE1vZGUgPSBtb2RlOwoJCQkJCQkJZWxzZSAvLyByZXN1bHQgPT0gOSAvLyBjYW5jZWwKCQkJCQkJCQlyZXR1cm47CgkJCQkJCX0KCQkJCQkJCgkJCQkJCWlmIChJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLmVxdWFscyhsYXVuY2hNb2RlKSkgewoJCQkJCQkJaWYgKCFicmVha3BvaW50TWFuYWdlci5pc0VuYWJsZWQoKSAmJiAhZGlzYWJsZWRCcmVha3BvaW50cykgewoJCQkJCQkJCWludCByZXN1bHQgPSBvcGVuQnJlYWtwb2ludERpYWxvZyhzaGVsbCk7CgkJCQkJCQkJaWYgKHJlc3VsdCA9PSAwKQoJCQkJCQkJCQlicmVha3BvaW50TWFuYWdlci5zZXRFbmFibGVkKHRydWUpOwoJCQkJCQkJCWVsc2UgaWYgKHJlc3VsdCA9PSAxKSB7CgkJCQkJCQkJCS8vIGlnbm9yZQoJCQkJCQkJCX0gZWxzZSAvLyByZXN1bHQgPT0gMgoJCQkJCQkJCQlyZXR1cm47CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQkJCgkJCQkJZmluYWwgTGF1bmNoQ2xpZW50Sm9iIGNsaWVudEpvYiA9IG5ldyBMYXVuY2hDbGllbnRKb2Ioc2VydmVyLCBtb2R1bGVzLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIsIGNsaWVudCk7CgkJCQkJaWYgKHJlc3RhcnQpIHsKCQkJCQkJZmluYWwgSVNlcnZlciBzZXJ2ZXIzID0gc2VydmVyOwoJCQkJCQlzZXJ2ZXIucmVzdGFydChsYXVuY2hNb2RlLCBuZXcgSVNlcnZlci5JT3BlcmF0aW9uTGlzdGVuZXIoKSB7CgkJCQkJCQlwdWJsaWMgdm9pZCBkb25lKElTdGF0dXMgcmVzdWx0KSB7CgkJCQkJCQkJLy8gT25seSBwdWJsaXNoIGlmIHRoZSBzZXJ2ZXIgcmVxdWlyZXMgcHVibGlzaCBiZWZvcmUgbGF1bmNoaW5nIHRoZSBjbGllbnQuCgkJCQkJCQkJaWYgKHNlcnZlcjMuc2hvdWxkUHVibGlzaCgpKSB7CgkJCQkJCQkJCXNlcnZlcjMucHVibGlzaChJU2VydmVyLlBVQkxJU0hfSU5DUkVNRU5UQUwsIG51bGwsIGluZm8sIG5ldyBJU2VydmVyLklPcGVyYXRpb25MaXN0ZW5lcigpIHsKCQkJCQkJCQkJCXB1YmxpYyB2b2lkIGRvbmUoSVN0YXR1cyByZXN1bHQyKSB7CgkJCQkJCQkJCQkJaWYgKHJlc3VsdDIuaXNPSygpKQoJCQkJCQkJCQkJCQljbGllbnRKb2Iuc2NoZWR1bGUoKTsKCQkJCQkJCQkJCX0KCQkJCQkJCQkJfSk7CgkJCQkJCQkJfSBlbHNlIHsKCQkJCQkJCQkJY2xpZW50Sm9iLnNjaGVkdWxlKCk7CgkJCQkJCQkJfQoJCQkJCQkJfQoJCQkJCQl9KTsKCQkJCQl9IGVsc2UgewoJCQkJCQkvLyBPbmx5IHB1Ymxpc2ggaWYgdGhlIHNlcnZlciByZXF1aXJlcyBwdWJsaXNoIGJlZm9yZSBsYXVuY2hpbmcgdGhlIGNsaWVudC4KCQkJCQkJaWYgKHNlcnZlci5zaG91bGRQdWJsaXNoKCkpIHsKCQkJCQkJCXNlcnZlci5wdWJsaXNoKElTZXJ2ZXIuUFVCTElTSF9JTkNSRU1FTlRBTCwgbnVsbCwgaW5mbywgbmV3IElTZXJ2ZXIuSU9wZXJhdGlvbkxpc3RlbmVyKCkgewoJCQkJCQkJCXB1YmxpYyB2b2lkIGRvbmUoSVN0YXR1cyByZXN1bHQpIHsKCQkJCQkJCQkJaWYgKHJlc3VsdC5pc09LKCkpCgkJCQkJCQkJCQljbGllbnRKb2Iuc2NoZWR1bGUoKTsKCQkJCQkJCQl9CgkJCQkJCQl9KTsKCQkJCQkJfSBlbHNlIHsKCQkJCQkJCWNsaWVudEpvYi5zY2hlZHVsZSgpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfSBlbHNlIGlmIChzdGF0ZSAhPSBJU2VydmVyLlNUQVRFX1NUT1BQSU5HKSB7CgkJCQkJZmluYWwgTGF1bmNoQ2xpZW50Sm9iIGNsaWVudEpvYiA9IG5ldyBMYXVuY2hDbGllbnRKb2Ioc2VydmVyLCBtb2R1bGVzLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIsIGNsaWVudCk7CgkJCQkJCgkJCQkJc2VydmVyLnN0YXJ0KGxhdW5jaE1vZGUsIG5ldyBJU2VydmVyLklPcGVyYXRpb25MaXN0ZW5lcigpIHsKCQkJCQkJcHVibGljIHZvaWQgZG9uZShJU3RhdHVzIHJlc3VsdCkgewoJCQkJCQkJaWYgKHJlc3VsdC5pc09LKCkpCgkJCQkJCQkJY2xpZW50Sm9iLnNjaGVkdWxlKCk7CgkJCQkJCX0KCQkJCQl9KTsKCQkJCX0KCQkJfQoJCX07CgkJdGhyZWFkLnNldERhZW1vbih0cnVlKTsKCQl0aHJlYWQuc3RhcnQoKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCBzZXR1cExhdW5jaENvbmZpZ3VyYXRpb24oSUxhdW5jaENvbmZpZ3VyYXRpb25Xb3JraW5nQ29weSBjb25maWcsIElTZXJ2ZXIgc2VydmVyLCBNb2R1bGVBcnRpZmFjdERlbGVnYXRlIG1vZHVsZUFydGlmYWN0LCBJTGF1bmNoYWJsZUFkYXB0ZXIgbGF1bmNoYWJsZUFkYXB0ZXIsIElDbGllbnQgY2xpZW50KSB7CgkJU3RyaW5nIGxhdW5jaE5hbWUgPSBOTFMuYmluZChNZXNzYWdlcy5ydW5PblNlcnZlckxhdW5jaENvbmZpZ05hbWUsIG1vZHVsZUFydGlmYWN0LmdldE5hbWUoKSk7CgkJbGF1bmNoTmFtZSA9IGdldFZhbGlkTGF1bmNoQ29uZmlndXJhdGlvbk5hbWUobGF1bmNoTmFtZSk7CgkJaWYgKCFsYXVuY2hOYW1lLmVxdWFscyhjb25maWcuZ2V0TmFtZSgpKSkgewoJCQlJTGF1bmNoTWFuYWdlciBsYXVuY2hNYW5hZ2VyID0gRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldExhdW5jaE1hbmFnZXIoKTsKCQkJbGF1bmNoTmFtZSA9IGxhdW5jaE1hbmFnZXIuZ2VuZXJhdGVVbmlxdWVMYXVuY2hDb25maWd1cmF0aW9uTmFtZUZyb20obGF1bmNoTmFtZSk7CgkJCWNvbmZpZy5yZW5hbWUobGF1bmNoTmFtZSk7CgkJfQoJCQoJCWNvbmZpZy5zZXRBdHRyaWJ1dGUoUnVuT25TZXJ2ZXJMYXVuY2hDb25maWd1cmF0aW9uRGVsZWdhdGUuQVRUUl9TRVJWRVJfSUQsIHNlcnZlci5nZXRJZCgpKTsKCQljb25maWcuc2V0QXR0cmlidXRlKFJ1bk9uU2VydmVyTGF1bmNoQ29uZmlndXJhdGlvbkRlbGVnYXRlLkFUVFJfTU9EVUxFX0FSVElGQUNULCBtb2R1bGVBcnRpZmFjdC5zZXJpYWxpemUoKSk7CgkJY29uZmlnLnNldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX01PRFVMRV9BUlRJRkFDVF9DTEFTUywgbW9kdWxlQXJ0aWZhY3QuZ2V0Q2xhc3MoKS5nZXROYW1lKCkpOwoJCWlmIChsYXVuY2hhYmxlQWRhcHRlciAhPSBudWxsKQoJCQljb25maWcuc2V0QXR0cmlidXRlKFJ1bk9uU2VydmVyTGF1bmNoQ29uZmlndXJhdGlvbkRlbGVnYXRlLkFUVFJfTEFVTkNIQUJMRV9BREFQVEVSX0lELCBsYXVuY2hhYmxlQWRhcHRlci5nZXRJZCgpKTsKCQllbHNlCgkJCWNvbmZpZy5zZXRBdHRyaWJ1dGUoUnVuT25TZXJ2ZXJMYXVuY2hDb25maWd1cmF0aW9uRGVsZWdhdGUuQVRUUl9MQVVOQ0hBQkxFX0FEQVBURVJfSUQsIChTdHJpbmcpbnVsbCk7CgkJY29uZmlnLnNldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX0NMSUVOVF9JRCwgY2xpZW50LmdldElkKCkpOwoJCQoJCXRyeSB7CgkJCUlQcm9qZWN0IHByb2plY3QgPSBtb2R1bGVBcnRpZmFjdC5nZXRNb2R1bGUoKS5nZXRQcm9qZWN0KCk7CgkJCWNvbmZpZy5zZXRNYXBwZWRSZXNvdXJjZXMobmV3IElSZXNvdXJjZVtdIHsgcHJvamVjdCB9KTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlpZiAoVHJhY2UuV0FSTklORykgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU1RSSU5HX1dBUk5JTkcsICJDb3VsZCBub3QgYXNzb2NpYXRlIGxhdW5jaCB3aXRoIGEgcHJvamVjdCIsIGUpOwoJCQl9CgkJfQoJfQoKCXByb3RlY3RlZCBJTGF1bmNoQ29uZmlndXJhdGlvbiBnZXRMYXVuY2hDb25maWd1cmF0aW9uKElTZXJ2ZXIgc2VydmVyLCBNb2R1bGVBcnRpZmFjdERlbGVnYXRlIG1vZHVsZUFydGlmYWN0LCBJTGF1bmNoYWJsZUFkYXB0ZXIgbGF1bmNoYWJsZUFkYXB0ZXIyLCBJQ2xpZW50IGNsaWVudDIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCVN0cmluZyBzZXJ2ZXJJZCA9IHNlcnZlci5nZXRJZCgpOwoJCUlMYXVuY2hNYW5hZ2VyIGxhdW5jaE1hbmFnZXIgPSBEZWJ1Z1BsdWdpbi5nZXREZWZhdWx0KCkuZ2V0TGF1bmNoTWFuYWdlcigpOwoJCUlMYXVuY2hDb25maWd1cmF0aW9uVHlwZSBsYXVuY2hDb25maWdUeXBlID0gbGF1bmNoTWFuYWdlci5nZXRMYXVuY2hDb25maWd1cmF0aW9uVHlwZSgib3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5sYXVuY2hDb25maWd1cmF0aW9uVHlwZSIpOwoJCUlMYXVuY2hDb25maWd1cmF0aW9uW10gbGF1bmNoQ29uZmlncyA9IG51bGw7CgkJdHJ5IHsKCQkJbGF1bmNoQ29uZmlncyA9IGxhdW5jaE1hbmFnZXIuZ2V0TGF1bmNoQ29uZmlndXJhdGlvbnMobGF1bmNoQ29uZmlnVHlwZSk7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCS8vIGlnbm9yZQoJCX0KCQkKCQlpZiAobGF1bmNoQ29uZmlncyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gbGF1bmNoQ29uZmlncy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlMaXN0IGxpc3QgPSBsYXVuY2hDb25maWdzW2ldLmdldEF0dHJpYnV0ZShJRGVidWdVSUNvbnN0YW50cy5BVFRSX0ZBVk9SSVRFX0dST1VQUywgKExpc3QpbnVsbCk7CgkJCQlpZiAobGlzdCA9PSBudWxsIHx8IGxpc3QuaXNFbXB0eSgpKSB7CgkJCQkJdHJ5IHsKCQkJCQkJU3RyaW5nIHNlcnZlcklkMiA9IGxhdW5jaENvbmZpZ3NbaV0uZ2V0QXR0cmlidXRlKFJ1bk9uU2VydmVyTGF1bmNoQ29uZmlndXJhdGlvbkRlbGVnYXRlLkFUVFJfU0VSVkVSX0lELCAoU3RyaW5nKSBudWxsKTsKCQkJCQkJaWYgKHNlcnZlcklkLmVxdWFscyhzZXJ2ZXJJZDIpKSB7CgkJCQkJCQlmaW5hbCBJTGF1bmNoQ29uZmlndXJhdGlvbldvcmtpbmdDb3B5IHdjID0gbGF1bmNoQ29uZmlnc1tpXS5nZXRXb3JraW5nQ29weSgpOwoJCQkJCQkJc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKHdjLCBzZXJ2ZXIsIG1vZHVsZUFydGlmYWN0LCBsYXVuY2hhYmxlQWRhcHRlcjIsIGNsaWVudDIpOwoJCQkJCQkJaWYgKHdjLmlzRGlydHkoKSkgewoJCQkJCQkJCXRyeSB7CgkJCQkJCQkJCXJldHVybiB3Yy5kb1NhdmUoKTsKCQkJCQkJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCQkJCQkJCWlmIChUcmFjZS5TRVZFUkUpIHsKCQkJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNUUklOR19TRVZFUkUsICJFcnJvciBjb25maWd1cmluZyBsYXVuY2giLCBjZSk7CgkJCQkJCQkJCX0KCQkJCQkJCQl9CgkJCQkJCQl9CgkJCQkJCQlyZXR1cm4gbGF1bmNoQ29uZmlnc1tpXTsKCQkJCQkJfQoJCQkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkJCQlpZiAoVHJhY2UuU0VWRVJFKSB7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfU0VWRVJFLCAiRXJyb3IgY29uZmlndXJpbmcgbGF1bmNoIiwgZSk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkJCgkJLy8gY3JlYXRlIGEgbmV3IGxhdW5jaCBjb25maWd1cmF0aW9uCgkJU3RyaW5nIGxhdW5jaE5hbWUgPSBOTFMuYmluZChNZXNzYWdlcy5ydW5PblNlcnZlckxhdW5jaENvbmZpZ05hbWUsIG1vZHVsZUFydGlmYWN0LmdldE5hbWUoKSk7CgkJbGF1bmNoTmFtZSA9IGdldFZhbGlkTGF1bmNoQ29uZmlndXJhdGlvbk5hbWUobGF1bmNoTmFtZSk7CgkJbGF1bmNoTmFtZSA9IGxhdW5jaE1hbmFnZXIuZ2VuZXJhdGVVbmlxdWVMYXVuY2hDb25maWd1cmF0aW9uTmFtZUZyb20obGF1bmNoTmFtZSk7IAoJCUlMYXVuY2hDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgd2MgPSBsYXVuY2hDb25maWdUeXBlLm5ld0luc3RhbmNlKG51bGwsIGxhdW5jaE5hbWUpOwoJCXdjLnNldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX1NFUlZFUl9JRCwgc2VydmVySWQpOwoJCXNldHVwTGF1bmNoQ29uZmlndXJhdGlvbih3Yywgc2VydmVyLCBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIyLCBjbGllbnQyKTsKCQlyZXR1cm4gd2MuZG9TYXZlKCk7Cgl9CgoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBjaGFyW10gSU5WQUxJRF9DSEFSUyA9IG5ldyBjaGFyW10geycvJywnXFwnLCAnOicsICcqJywgJz8nLCAnIicsICc8JywgJz4nLCAnfCcsICdcMCcsICdAJywgJyYnfTsKCXByb3RlY3RlZCBTdHJpbmcgZ2V0VmFsaWRMYXVuY2hDb25maWd1cmF0aW9uTmFtZShTdHJpbmcgcykgewoJCWlmIChzID09IG51bGwgfHwgcy5sZW5ndGgoKSA9PSAwKQoJCQlyZXR1cm4gIjEiOwoJCWludCBzaXplID0gSU5WQUxJRF9DSEFSUy5sZW5ndGg7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJcyA9IHMucmVwbGFjZShJTlZBTElEX0NIQVJTW2ldLCAnXycpOwoJCX0KCQlyZXR1cm4gczsKCX0KCgkvKioKCSAqIE9wZW4gYW4gb3B0aW9ucyBkaWFsb2cuCgkgKiAKCSAqIEBwYXJhbSBzaGVsbAoJICogQHBhcmFtIHRpdGxlCgkgKiBAcGFyYW0gbWVzc2FnZQoJICogQHBhcmFtIGJyZWFrcG9pbnRzT3B0aW9uCgkgKiBAcmV0dXJuIGEgZGlhbG9nIHJldHVybiBjb25zdGFudAoJICovCglwcm90ZWN0ZWQgc3RhdGljIGludCBvcGVuT3B0aW9uc0RpYWxvZyhmaW5hbCBTaGVsbCBzaGVsbCwgZmluYWwgU3RyaW5nIHRpdGxlLCBmaW5hbCBTdHJpbmcgbWVzc2FnZSwgZmluYWwgYm9vbGVhbiBicmVha3BvaW50c09wdGlvbikgewoJCWlmIChicmVha3BvaW50c09wdGlvbikgewoJCQlpbnQgY3VycmVudCA9IFNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuZ2V0TGF1bmNoTW9kZTIoKTsKCQkJaWYgKGN1cnJlbnQgPT0gU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfUkVTVEFSVCkKCQkJCXJldHVybiAwOwoJCQllbHNlIGlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREUyX0RJU0FCTEVfQlJFQUtQT0lOVFMpCgkJCQlyZXR1cm4gMTsKCQkJZWxzZSBpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLkxBVU5DSF9NT0RFMl9DT05USU5VRSkKCQkJCXJldHVybiAyOwoJCX0gZWxzZSB7CgkJCWludCBjdXJyZW50ID0gU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5nZXRMYXVuY2hNb2RlKCk7CgkJCWlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREVfUkVTVEFSVCkKCQkJCXJldHVybiAwOwoJCQllbHNlIGlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREVfQ09OVElOVUUpCgkJCQlyZXR1cm4gMTsKCQl9CgkJZmluYWwgaW50W10gaSA9IG5ldyBpbnRbMV07CgkJc2hlbGwuZ2V0RGlzcGxheSgpLnN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJT3B0aW9uc01lc3NhZ2VEaWFsb2cgZGlhbG9nID0gbnVsbDsKCQkJCVN0cmluZ1tdIGl0ZW1zID0gbnVsbDsKCQkJCWlmIChicmVha3BvaW50c09wdGlvbikgewoJCQkJCWl0ZW1zID0gbmV3IFN0cmluZ1tdIHsKCQkJCQkJTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdSZXN0YXJ0LAoJCQkJCQlNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0JyZWFrcG9pbnRzLAoJCQkJCQlNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0NvbnRpbnVlCgkJCQkJfTsKCQkJCX0gZWxzZSB7CgkJCQkJaXRlbXMgPSBuZXcgU3RyaW5nW10gewoJCQkJCQlNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ1Jlc3RhcnQsCgkJCQkJCU1lc3NhZ2VzLmRpYWxvZ01vZGVXYXJuaW5nQ29udGludWUKCQkJCQl9OwoJCQkJfQoJCQkJCgkJCQlkaWFsb2cgPSBuZXcgT3B0aW9uc01lc3NhZ2VEaWFsb2coc2hlbGwsIHRpdGxlLCBtZXNzYWdlLCBpdGVtcyk7CgkJCQlpWzBdID0gZGlhbG9nLm9wZW4oKTsKCQkJCQoJCQkJaWYgKGRpYWxvZy5pc1JlbWVtYmVyKCkpIHsKCQkJCQlpZiAoYnJlYWtwb2ludHNPcHRpb24pIHsKCQkJCQkJaWYgKGlbMF0gPT0gMCkKCQkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0TGF1bmNoTW9kZTIoU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfUkVTVEFSVCk7CgkJCQkJCWVsc2UgaWYgKGlbMF0gPT0gMSkKCQkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0TGF1bmNoTW9kZTIoU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfRElTQUJMRV9CUkVBS1BPSU5UUyk7CgkJCQkJCWVsc2UgaWYgKGlbMF0gPT0gMikKCQkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0TGF1bmNoTW9kZTIoU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfQ09OVElOVUUpOwoJCQkJCX0gZWxzZSB7CgkJCQkJCWlmIChpWzBdID09IDApCgkJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldExhdW5jaE1vZGUoU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERV9SRVNUQVJUKTsKCQkJCQkJZWxzZSBpZiAoaVswXSA9PSAxKQoJCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRMYXVuY2hNb2RlKFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREVfQ09OVElOVUUpOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0pOwoJCXJldHVybiBpWzBdOwoJfQoKCS8qKgoJICogT3BlbiBhbiBvcHRpb25zIGRpYWxvZy4KCSAqIAoJICogQHBhcmFtIHNoZWxsCgkgKiBAcmV0dXJuIGEgZGlhbG9nIHJldHVybiBjb25zdGFudAoJICovCglwcm90ZWN0ZWQgc3RhdGljIGludCBvcGVuQnJlYWtwb2ludERpYWxvZyhmaW5hbCBTaGVsbCBzaGVsbCkgewoJCWludCBjdXJyZW50ID0gU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5nZXRFbmFibGVCcmVha3BvaW50cygpOwoJCWlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuRU5BQkxFX0JSRUFLUE9JTlRTX0FMV0FZUykKCQkJcmV0dXJuIDA7CgkJZWxzZSBpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLkVOQUJMRV9CUkVBS1BPSU5UU19ORVZFUikKCQkJcmV0dXJuIDE7CgkJCgkJZmluYWwgaW50W10gaSA9IG5ldyBpbnRbMV07CgkJc2hlbGwuZ2V0RGlzcGxheSgpLnN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJT3B0aW9uc01lc3NhZ2VEaWFsb2cgZGlhbG9nID0gbmV3IE9wdGlvbnNNZXNzYWdlRGlhbG9nKHNoZWxsLAoJCQkJCQlNZXNzYWdlcy53aXpEZWJ1Z09uU2VydmVyVGl0bGUsIE1lc3NhZ2VzLmRpYWxvZ0JyZWFrcG9pbnRzLCBuZXcgU3RyaW5nW10gewoJCQkJCQlNZXNzYWdlcy5kaWFsb2dCcmVha3BvaW50c1JlZW5hYmxlLCBNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0NvbnRpbnVlfSk7CgkJCQlpWzBdID0gZGlhbG9nLm9wZW4oKTsKCQkJCWlmIChkaWFsb2cuaXNSZW1lbWJlcigpKSB7CgkJCQkJaWYgKGlbMF0gPT0gMCkKCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRFbmFibGVCcmVha3BvaW50cyhTZXJ2ZXJVSVByZWZlcmVuY2VzLkVOQUJMRV9CUkVBS1BPSU5UU19BTFdBWVMpOwoJCQkJCWVsc2UgaWYgKGlbMF0gPT0gMSkKCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRFbmFibGVCcmVha3BvaW50cyhTZXJ2ZXJVSVByZWZlcmVuY2VzLkVOQUJMRV9CUkVBS1BPSU5UU19ORVZFUik7CgkJCQl9CgkJCX0KCQl9KTsKCQlyZXR1cm4gaVswXTsKCX0KCgkvKioKCSAqIE9wZW4gYSByZXN0YXJ0IG9wdGlvbnMgZGlhbG9nLgoJICogCgkgKiBAcGFyYW0gc2hlbGwKCSAqIEByZXR1cm4gYSBkaWFsb2cgcmV0dXJuIGNvbnN0YW50CgkgKi8KCXByb3RlY3RlZCBzdGF0aWMgaW50IG9wZW5SZXN0YXJ0RGlhbG9nKGZpbmFsIFNoZWxsIHNoZWxsKSB7CgkJaW50IGN1cnJlbnQgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLmdldFJlc3RhcnQoKTsKCQlpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLlJFU1RBUlRfQUxXQVlTKQoJCQlyZXR1cm4gMDsKCQllbHNlIGlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuUkVTVEFSVF9ORVZFUikKCQkJcmV0dXJuIDE7CgkJCgkJZmluYWwgaW50W10gaSA9IG5ldyBpbnRbMV07CgkJc2hlbGwuZ2V0RGlzcGxheSgpLnN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJT3B0aW9uc01lc3NhZ2VEaWFsb2cgZGlhbG9nID0gbmV3IE9wdGlvbnNNZXNzYWdlRGlhbG9nKHNoZWxsLAoJCQkJCQlNZXNzYWdlcy5kZWZhdWx0RGlhbG9nVGl0bGUsIE1lc3NhZ2VzLmRpYWxvZ1Jlc3RhcnQsIG5ldyBTdHJpbmdbXSB7CgkJCQkJCU1lc3NhZ2VzLmRpYWxvZ1Jlc3RhcnRSZXN0YXJ0LCBNZXNzYWdlcy5kaWFsb2dSZXN0YXJ0Q29udGludWV9KTsKCQkJCWlbMF0gPSBkaWFsb2cub3BlbigpOwoJCQkJaWYgKGRpYWxvZy5pc1JlbWVtYmVyKCkpIHsKCQkJCQlpZiAoaVswXSA9PSAwKQoJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldFJlc3RhcnQoU2VydmVyVUlQcmVmZXJlbmNlcy5SRVNUQVJUX0FMV0FZUyk7CgkJCQkJZWxzZSBpZiAoaVswXSA9PSAxKQoJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldFJlc3RhcnQoU2VydmVyVUlQcmVmZXJlbmNlcy5SRVNUQVJUX05FVkVSKTsKCQkJCX0KCQkJfQoJCX0pOwoJCXJldHVybiBpWzBdOwoJfQoKCS8qKgoJICogVGhlIGRlbGVnYXRpbmcgYWN0aW9uIGhhcyBiZWVuIHBlcmZvcm1lZC4gSW1wbGVtZW50CgkgKiB0aGlzIG1ldGhvZCB0byBkbyB0aGUgYWN0dWFsIHdvcmsuCgkgKgoJICogQHBhcmFtIGFjdGlvbiBhY3Rpb24gcHJveHkgdGhhdCBoYW5kbGVzIHRoZSBwcmVzZW50YXRpb24KCSAqIHBvcnRpb24gb2YgdGhlIHBsdWdpbiBhY3Rpb24KCSAqLwoJcHVibGljIHZvaWQgcnVuKElBY3Rpb24gYWN0aW9uKSB7CgkJaWYgKFRyYWNlLkZJTkVTVCkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfRklORVNULCAiUnVubmluZyBvbiBTZXJ2ZXIuLi4iKTsKCQl9CgkJdHJ5IHsKCQkJcnVuKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJaWYgKFRyYWNlLlNFVkVSRSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU1RSSU5HX1NFVkVSRSwgIlJ1biBvbiBTZXJ2ZXIgRXJyb3IiLCBlKTsKCQkJfQoJCX0KCX0KCglwcm90ZWN0ZWQgYm9vbGVhbiBpc0VuYWJsZWQoKSB7CgkJdHJ5IHsKCQkJQm9vbGVhbiBiID0gZ2xvYmFsTGF1bmNoTW9kZS5nZXQoZ2V0TGF1bmNoTW9kZSgpKTsKCQkJcmV0dXJuIGIuYm9vbGVhblZhbHVlKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIHN0YXJ0IG1vZGUgdGhhdCB0aGUgc2VydmVyIHNob3VsZCB1c2UuCgkgKi8KCXByb3RlY3RlZCBTdHJpbmcgZ2V0TGF1bmNoTW9kZSgpIHsKCQlyZXR1cm4gbGF1bmNoTW9kZTsKCX0KCgkvKioKCSAqIFNldCB0aGUgbGF1bmNoIG1vZGUuCgkgKiAKCSAqIEBwYXJhbSBsYXVuY2hNb2RlIGEge0BsaW5rIElMYXVuY2hNYW5hZ2VyfSBsYXVuY2ggbW9kZQoJICovCglwdWJsaWMgdm9pZCBzZXRMYXVuY2hNb2RlKFN0cmluZyBsYXVuY2hNb2RlKSB7CgkJdGhpcy5sYXVuY2hNb2RlID0gbGF1bmNoTW9kZTsKCX0KCgkvKioKCSAqIERldGVybWluZSB3aGljaCBjbGllbnRzIGNhbiBhY3Qgb24gdGhlIGN1cnJlbnQgc2VsZWN0aW9uLgoJICoKCSAqIEBwYXJhbSBhY3Rpb24gYWN0aW9uIHByb3h5IHRoYXQgaGFuZGxlcyBwcmVzZW50YXRpb24KCSAqICAgIHBvcnRpb24gb2YgdGhlIHBsdWdpbiBhY3Rpb24KCSAqIEBwYXJhbSBzZWwgY3VycmVudCBzZWxlY3Rpb24gaW4gdGhlIGRlc2t0b3AKCSAqLwoJcHVibGljIHZvaWQgc2VsZWN0aW9uQ2hhbmdlZChJQWN0aW9uIGFjdGlvbiwgSVNlbGVjdGlvbiBzZWwpIHsKCQlpZiAoVHJhY2UuRklORVNUKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNUUklOR19GSU5FU1QsICI+IHNlbGVjdGlvbkNoYW5nZWQiKTsKCQl9CgkJc2VsZWN0aW9uID0gbnVsbDsKCQlsb25nIHRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQlpZiAoc2VsID09IG51bGwgfHwgc2VsLmlzRW1wdHkoKSB8fCAhKHNlbCBpbnN0YW5jZW9mIElTdHJ1Y3R1cmVkU2VsZWN0aW9uKSkgewoJCQlhY3Rpb24uc2V0RW5hYmxlZChmYWxzZSk7CgkJCWdsb2JhbFNlbGVjdGlvbiA9IG51bGw7CgkJCXJldHVybjsKCQl9CgkJCgkJSVN0cnVjdHVyZWRTZWxlY3Rpb24gc2VsZWN0ID0gKElTdHJ1Y3R1cmVkU2VsZWN0aW9uKSBzZWw7CgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBzZWxlY3QuaXRlcmF0b3IoKTsKCQlpZiAoaXRlcmF0b3IuaGFzTmV4dCgpKQoJCQlzZWxlY3Rpb24gPSBpdGVyYXRvci5uZXh0KCk7CgkJaWYgKGl0ZXJhdG9yLmhhc05leHQoKSkgeyAvLyBtb3JlIHRoYW4gb25lIHNlbGVjdGlvbiAoc2hvdWxkIG5ldmVyIGhhcHBlbikKCQkJYWN0aW9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCQlzZWxlY3Rpb24gPSBudWxsOwoJCQlnbG9iYWxTZWxlY3Rpb24gPSBudWxsOwoJCQlyZXR1cm47CgkJfQoJCQoJCWlmIChzZWxlY3Rpb24gIT0gZ2xvYmFsU2VsZWN0aW9uKSB7CgkJCWlmIChUcmFjZS5GSU5FU1QpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNUUklOR19GSU5FU1QsICJTZWxlY3Rpb246ICIgKyBzZWxlY3Rpb24pOwoJCQl9CgkJCWlmIChzZWxlY3Rpb24gIT0gbnVsbCkKCQkJCWlmIChUcmFjZS5GSU5FU1QpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfRklORVNULCAiU2VsZWN0aW9uIHR5cGU6ICIgKyBzZWxlY3Rpb24uZ2V0Q2xhc3MoKS5nZXROYW1lKCkpOwoJCQkJfQoJCQlnbG9iYWxTZWxlY3Rpb24gPSBzZWxlY3Rpb247CgkJCWdsb2JhbExhdW5jaE1vZGUgPSBuZXcgSGFzaE1hcDxTdHJpbmcsIEJvb2xlYW4+KCk7CgkJCWlmICghU2VydmVyUGx1Z2luLmhhc01vZHVsZUFydGlmYWN0KGdsb2JhbFNlbGVjdGlvbikpIHsKCQkJCWFjdGlvbi5zZXRFbmFibGVkKGZhbHNlKTsKCQkJCXJldHVybjsKCQkJfQoJCQkKCQkJaWYgKFRyYWNlLkZJTkVTVCkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU1RSSU5HX0ZJTkVTVCwgImNoZWNraW5nIGZvciBtb2R1bGUgYXJ0aWZhY3QiKTsKCQkJfQoJCQkvLyBUT0RPIC0gbXVsdGlwbGUgbW9kdWxlIGFydGlmYWN0cwoJCQlJTW9kdWxlQXJ0aWZhY3RbXSBtb2R1bGVBcnRpZmFjdHMgPSBTZXJ2ZXJQbHVnaW4uZ2V0TW9kdWxlQXJ0aWZhY3RzKGdsb2JhbFNlbGVjdGlvbik7CgkJCUlNb2R1bGVBcnRpZmFjdCBtb2R1bGVBcnRpZmFjdCA9IG51bGw7CgkJCWlmIChtb2R1bGVBcnRpZmFjdHMgIT0gbnVsbCAmJiBtb2R1bGVBcnRpZmFjdHMubGVuZ3RoID4gMCkKCQkJCW1vZHVsZUFydGlmYWN0ID0gbW9kdWxlQXJ0aWZhY3RzWzBdOwoJCQkKCQkJSU1vZHVsZSBtb2R1bGUgPSBudWxsOwoJCQlpZiAobW9kdWxlQXJ0aWZhY3QgIT0gbnVsbCkKCQkJCW1vZHVsZSA9IG1vZHVsZUFydGlmYWN0LmdldE1vZHVsZSgpOwoJCQlpZiAoVHJhY2UuRklORVNUKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5TVFJJTkdfRklORVNULCAibW9kdWxlQXJ0aWZhY3Q9ICIgKyBtb2R1bGVBcnRpZmFjdCArICIsIG1vZHVsZT0gIiArIG1vZHVsZSk7CgkJCX0KCQkJaWYgKG1vZHVsZSAhPSBudWxsKQoJCQkJZmluZEdsb2JhbExhdW5jaE1vZGVzKG1vZHVsZSk7CgkJCWVsc2UgewoJCQkJZ2xvYmFsTGF1bmNoTW9kZS5wdXQoSUxhdW5jaE1hbmFnZXIuUlVOX01PREUsIG5ldyBCb29sZWFuKHRydWUpKTsKCQkJCWdsb2JhbExhdW5jaE1vZGUucHV0KElMYXVuY2hNYW5hZ2VyLkRFQlVHX01PREUsIG5ldyBCb29sZWFuKHRydWUpKTsKCQkJCWdsb2JhbExhdW5jaE1vZGUucHV0KElMYXVuY2hNYW5hZ2VyLlBST0ZJTEVfTU9ERSwgbmV3IEJvb2xlYW4odHJ1ZSkpOwoJCQl9CgkJfQoJCQoJCWFjdGlvbi5zZXRFbmFibGVkKGlzRW5hYmxlZCgpKTsKCQlpZiAoVHJhY2UuRklORVNUKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNUUklOR19GSU5FU1QsICI8IHNlbGVjdGlvbkNoYW5nZWQgIiArIChTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSAtIHRpbWUpKTsKCQl9Cgl9CgoJLyoqCgkgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlcmUgaXMgYSBzZXJ2ZXIgZmFjdG9yeSBhdmFpbGFibGUgZm9yIHRoZSBnaXZlbiBtb2R1bGUKCSAqIGFuZCB0aGUgdmFyaW91cyBzdGFydCBtb2Rlcy4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmluZEdsb2JhbExhdW5jaE1vZGVzKElNb2R1bGUgbW9kdWxlKSB7CgkJSVNlcnZlclR5cGVbXSBzZXJ2ZXJUeXBlcyA9IFNlcnZlckNvcmUuZ2V0U2VydmVyVHlwZXMoKTsKCQlpZiAoc2VydmVyVHlwZXMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IHNlcnZlclR5cGVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCUlTZXJ2ZXJUeXBlIHR5cGUgPSBzZXJ2ZXJUeXBlc1tpXTsKCQkJCWlmIChpc1ZhbGlkU2VydmVyVHlwZSh0eXBlLCBtb2R1bGUpKSB7CgkJCQkJZm9yIChieXRlIGIgPSAwOyBiIDwgbGF1bmNoTW9kZXMubGVuZ3RoOyBiKyspIHsKCQkJCQkJaWYgKHR5cGUuc3VwcG9ydHNMYXVuY2hNb2RlKGxhdW5jaE1vZGVzW2JdKSkgewoJCQkJCQkJZ2xvYmFsTGF1bmNoTW9kZS5wdXQobGF1bmNoTW9kZXNbYl0sIG5ldyBCb29sZWFuKHRydWUpKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCX0KCgkvKioKCSAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgZ2l2ZW4gc2VydmVyIHR5cGUgY2FuIGxhdW5jaCB0aGUgbW9kdWxlLiAKCSAqLwoJcHJvdGVjdGVkIGJvb2xlYW4gaXNWYWxpZFNlcnZlclR5cGUoSVNlcnZlclR5cGUgdHlwZSwgSU1vZHVsZSBtb2R1bGUpIHsKCQl0cnkgewoJCQlJUnVudGltZVR5cGUgcnVudGltZVR5cGUgPSB0eXBlLmdldFJ1bnRpbWVUeXBlKCk7CgkJCVNlcnZlclV0aWwuaXNTdXBwb3J0ZWRNb2R1bGUocnVudGltZVR5cGUuZ2V0TW9kdWxlVHlwZXMoKSwgbW9kdWxlLmdldE1vZHVsZVR5cGUoKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQlyZXR1cm4gdHJ1ZTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgc2V0TWFwKEhhc2hNYXA8U3RyaW5nLE9iamVjdD4gbWFwKXsKCQl0aGlzLndpel9wcm9wZXJ0aWVzID0gbWFwOwoJfQoJCgkvKioKCSAqIFJldHVybnMgdGhlIHZhbHVlIGZyb20gdGhlIGhhc2htYXAgcHJvdmlkZWQgaW4gdGhlIGNvbnN0cnVjdG9yIG9mIHRoaXMgY2xhc3MKCSAqICAKCSAqIEBwYXJhbSBrZXkgIAoJICogQHBhcmFtIG9iaiB0aGUgdHlwZSBvZiBvYmplY3QgdG8gYmUgcmV0dXJuZWQKCSAqIEByZXR1cm4KCSAqLwoJcHJvdGVjdGVkIE9iamVjdCBnZXRPdmVyd3JpdGVWYWx1ZShTdHJpbmcga2V5KXsKCQlpZiAod2l6X3Byb3BlcnRpZXMgIT0gbnVsbCl7IAoJCQlPYmplY3QgbyA9IHdpel9wcm9wZXJ0aWVzLmdldChrZXkpOwoJCQlyZXR1cm4gbzsJCgkJfQoJCXJldHVybiBudWxsOwoJfQp9