LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA3IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuYWN0aW9uczsKCmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRm9sZGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLio7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuam9icy5Kb2I7CmltcG9ydCBvcmcuZWNsaXBzZS5kZWJ1Zy5jb3JlLio7CmltcG9ydCBvcmcuZWNsaXBzZS5kZWJ1Zy51aS5JRGVidWdVSUNvbnN0YW50czsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmFjdGlvbi5JQWN0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UuZGlhbG9ncy5FcnJvckRpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuSVNlbGVjdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuSVN0cnVjdHVyZWRTZWxlY3Rpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS53aW5kb3cuV2luZG93OwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2Uud2l6YXJkLldpemFyZERpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLklDbGllbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuSUxhdW5jaGFibGVBZGFwdGVyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLlB1Ymxpc2hTZXJ2ZXJKb2I7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuUmVzdGFydFNlcnZlckpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5TZXJ2ZXJQbHVnaW47CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuU2VydmVyVHlwZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5TdGFydFNlcnZlckpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5UcmFjZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC5Nb2R1bGVBcnRpZmFjdERlbGVnYXRlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC52aWV3ZXJzLk1vZHVsZUFydGlmYWN0Q29tcG9zaXRlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC53aXphcmQuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLm9zZ2kudXRpbC5OTFM7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5EaXNwbGF5OwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuU2hlbGw7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5JV29ya2JlbmNoV2luZG93OwppbXBvcnQgb3JnLmVjbGlwc2UudWkuSVdvcmtiZW5jaFdpbmRvd0FjdGlvbkRlbGVnYXRlOwovKioKICogU3VwcG9ydCBmb3Igc3RhcnRpbmcvc3RvcHBpbmcgc2VydmVyIGFuZCBjbGllbnRzIGZvciByZXNvdXJjZXMgcnVubmluZyBvbiBhIHNlcnZlci4KICovCnB1YmxpYyBjbGFzcyBSdW5PblNlcnZlckFjdGlvbkRlbGVnYXRlIGltcGxlbWVudHMgSVdvcmtiZW5jaFdpbmRvd0FjdGlvbkRlbGVnYXRlIHsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nW10gbGF1bmNoTW9kZXMgPSB7CgkJSUxhdW5jaE1hbmFnZXIuUlVOX01PREUsIElMYXVuY2hNYW5hZ2VyLkRFQlVHX01PREUsIElMYXVuY2hNYW5hZ2VyLlBST0ZJTEVfTU9ERSB9OwoKCXByb3RlY3RlZCBPYmplY3Qgc2VsZWN0aW9uOwoKCXByb3RlY3RlZCBJV29ya2JlbmNoV2luZG93IHdpbmRvdzsKCglwcm90ZWN0ZWQgc3RhdGljIE9iamVjdCBnbG9iYWxTZWxlY3Rpb247CgoJcHJvdGVjdGVkIHN0YXRpYyBNYXAgZ2xvYmFsTGF1bmNoTW9kZTsKCXByb3RlY3RlZCBTdHJpbmcgbGF1bmNoTW9kZSA9IElMYXVuY2hNYW5hZ2VyLlJVTl9NT0RFOwoKCXByb3RlY3RlZCBib29sZWFuIHRhc2tzQW5kQ2xpZW50U2hvd247CgoJcHJvdGVjdGVkIElMYXVuY2hhYmxlQWRhcHRlciBsYXVuY2hhYmxlQWRhcHRlcjsKCXByb3RlY3RlZCBJQ2xpZW50IGNsaWVudDsKCgkvKioKCSAqIFJ1bk9uU2VydmVyQWN0aW9uRGVsZWdhdGUgY29uc3RydWN0b3IgY29tbWVudC4KCSAqLwoJcHVibGljIFJ1bk9uU2VydmVyQWN0aW9uRGVsZWdhdGUoKSB7CgkJc3VwZXIoKTsKCX0KCgkvKioKCSAqIERpc3Bvc2VzIHRoaXMgYWN0aW9uIGRlbGVnYXRlLiAgVGhlIGltcGxlbWVudG9yIHNob3VsZCB1bmhvb2sgYW55IHJlZmVyZW5jZXMKCSAqIHRvIGl0c2VsZiBzbyB0aGF0IGdhcmJhZ2UgY29sbGVjdGlvbiBjYW4gb2NjdXIuCgkgKi8KCXB1YmxpYyB2b2lkIGRpc3Bvc2UoKSB7CgkJd2luZG93ID0gbnVsbDsKCX0KCgkvKioKCSAqIEluaXRpYWxpemVzIHRoaXMgYWN0aW9uIGRlbGVnYXRlIHdpdGggdGhlIHdvcmtiZW5jaCB3aW5kb3cgaXQgd2lsbCB3b3JrIGluLgoJICoKCSAqIEBwYXJhbSBuZXdXaW5kb3cgdGhlIHdpbmRvdyB0aGF0IHByb3ZpZGVzIHRoZSBjb250ZXh0IGZvciB0aGlzIGRlbGVnYXRlCgkgKi8KCXB1YmxpYyB2b2lkIGluaXQoSVdvcmtiZW5jaFdpbmRvdyBuZXdXaW5kb3cpIHsKCQl3aW5kb3cgPSBuZXdXaW5kb3c7Cgl9CgoJcHVibGljIElTZXJ2ZXIgZ2V0U2VydmVyKElNb2R1bGUgbW9kdWxlLCBJTW9kdWxlQXJ0aWZhY3QgbW9kdWxlQXJ0aWZhY3QsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUlTZXJ2ZXIgc2VydmVyID0gU2VydmVyQ29yZS5nZXREZWZhdWx0U2VydmVyKG1vZHVsZSk7CgkJCgkJLy8gaWdub3JlIHByZWZlcmVuY2UgaWYgdGhlIHNlcnZlciBkb2Vzbid0IHN1cHBvcnQgdGhpcyBtb2RlLgoJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiAhU2VydmVyVUlQbHVnaW4uaXNDb21wYXRpYmxlV2l0aExhdW5jaE1vZGUoc2VydmVyLCBsYXVuY2hNb2RlKSkKCQkJc2VydmVyID0gbnVsbDsKCQkKCQlpZiAoc2VydmVyICE9IG51bGwgJiYgIVNlcnZlclV0aWwuY29udGFpbnNNb2R1bGUoc2VydmVyLCBtb2R1bGUsIG1vbml0b3IpKSB7CgkJCUlTZXJ2ZXJXb3JraW5nQ29weSB3YyA9IHNlcnZlci5jcmVhdGVXb3JraW5nQ29weSgpOwoJCQl0cnkgewoJCQkJU2VydmVyVXRpbC5tb2RpZnlNb2R1bGVzKHdjLCBuZXcgSU1vZHVsZVtdIHsgbW9kdWxlIH0sIG5ldyBJTW9kdWxlWzBdLCBtb25pdG9yKTsKCQkJCXdjLnNhdmUoZmFsc2UsIG1vbml0b3IpOwoJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJDb3VsZCBub3QgYWRkIG1vZHVsZSB0byBzZXJ2ZXIiLCBjZSk7CgkJCQlzZXJ2ZXIgPSBudWxsOwoJCQl9CgkJfQoJCQoJCVNoZWxsIHNoZWxsOwoJCWlmICh3aW5kb3cgIT0gbnVsbCkKCQkJc2hlbGwgPSB3aW5kb3cuZ2V0U2hlbGwoKTsKCQllbHNlCgkJCXNoZWxsID0gU2VydmVyVUlQbHVnaW4uZ2V0SW5zdGFuY2UoKS5nZXRXb3JrYmVuY2goKS5nZXRBY3RpdmVXb3JrYmVuY2hXaW5kb3coKS5nZXRTaGVsbCgpOwoJCQoJCWlmIChzZXJ2ZXIgPT0gbnVsbCkgewoJCQkvLyB0cnkgdGhlIGZ1bGwgd2l6YXJkCgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkxhdW5jaGluZyB3aXphcmQiKTsKCQkJUnVuT25TZXJ2ZXJXaXphcmQgd2l6YXJkID0gbmV3IFJ1bk9uU2VydmVyV2l6YXJkKG1vZHVsZSwgbGF1bmNoTW9kZSwgbW9kdWxlQXJ0aWZhY3QpOwoJCQlDbG9zYWJsZVdpemFyZERpYWxvZyBkaWFsb2cgPSBuZXcgQ2xvc2FibGVXaXphcmREaWFsb2coc2hlbGwsIHdpemFyZCk7CgkJCWlmIChkaWFsb2cub3BlbigpID09IFdpbmRvdy5DQU5DRUwpIHsKCQkJCWlmIChtb25pdG9yICE9IG51bGwpCgkJCQkJbW9uaXRvci5zZXRDYW5jZWxlZCh0cnVlKTsKCQkJCXJldHVybiBudWxsOwoJCQl9CgkJCQoJCQl0cnkgewoJCQkJSm9iLmdldEpvYk1hbmFnZXIoKS5qb2luKCJvcmcuZWNsaXBzZS53c3Quc2VydmVyLnVpLmZhbWlseSIsIG51bGwpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuV0FSTklORywgIkVycm9yIHdhaXRpbmcgZm9yIGpvYiIsIGUpOwoJCQl9CgkJCXNlcnZlciA9IHdpemFyZC5nZXRTZXJ2ZXIoKTsKCQkJYm9vbGVhbiBwcmVmZXJyZWQgPSB3aXphcmQuaXNQcmVmZXJyZWRTZXJ2ZXIoKTsKCQkJdGFza3NBbmRDbGllbnRTaG93biA9IHRydWU7CgkJCWNsaWVudCA9IHdpemFyZC5nZXRTZWxlY3RlZENsaWVudCgpOwoJCQlsYXVuY2hhYmxlQWRhcHRlciA9IHdpemFyZC5nZXRMYXVuY2hhYmxlQWRhcHRlcigpOwoJCQkKCQkJLy8gc2V0IHByZWZlcnJlZCBzZXJ2ZXIgaWYgcmVxdWVzdGVkCgkJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiBwcmVmZXJyZWQpIHsKCQkJCXRyeSB7CgkJCQkJU2VydmVyQ29yZS5zZXREZWZhdWx0U2VydmVyKG1vZHVsZSwgc2VydmVyLCBtb25pdG9yKTsKCQkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJCQlTdHJpbmcgbWVzc2FnZSA9IE1lc3NhZ2VzLmVycm9yQ291bGROb3RTYXZlUHJlZmVyZW5jZTsKCQkJCQlFcnJvckRpYWxvZy5vcGVuRXJyb3Ioc2hlbGwsIE1lc3NhZ2VzLmVycm9yRGlhbG9nVGl0bGUsIG1lc3NhZ2UsIGNlLmdldFN0YXR1cygpKTsKCQkJCX0KCQkJfQoJCX0KCQkKCQl0cnkgewoJCQlKb2IuZ2V0Sm9iTWFuYWdlcigpLmpvaW4oIm9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuZmFtaWx5IiwgbmV3IE51bGxQcm9ncmVzc01vbml0b3IoKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuV0FSTklORywgIkVycm9yIHdhaXRpbmcgZm9yIGpvYiIsIGUpOwoJCX0KCQkKCQlyZXR1cm4gc2VydmVyOwoJfQoKCS8qKgoJICogUnVuIHRoZSByZXNvdXJjZSBvbiBhIHNlcnZlci4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgcnVuKCkgewoJCWZpbmFsIElNb2R1bGVBcnRpZmFjdFtdIG1vZHVsZUFydGlmYWN0cyA9IFNlcnZlclBsdWdpbi5nZXRNb2R1bGVBcnRpZmFjdHMoc2VsZWN0aW9uKTsKCQlpZiAobW9kdWxlQXJ0aWZhY3RzID09IG51bGwgfHwgbW9kdWxlQXJ0aWZhY3RzLmxlbmd0aCA9PSAwIHx8IG1vZHVsZUFydGlmYWN0c1swXSA9PSBudWxsKSB7CgkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihNZXNzYWdlcy5lcnJvck5vQXJ0aWZhY3QpOwoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJObyBtb2R1bGUgYXJ0aWZhY3QgZm91bmQiKTsKCQkJcmV0dXJuOwoJCX0KCQkKCQlTaGVsbCBzaGVsbDIgPSBudWxsOwoJCWlmICh3aW5kb3cgIT0gbnVsbCkKCQkJc2hlbGwyID0gd2luZG93LmdldFNoZWxsKCk7CgkJZWxzZSB7CgkJCXRyeSB7CgkJCQlzaGVsbDIgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRJbnN0YW5jZSgpLmdldFdvcmtiZW5jaCgpLmdldEFjdGl2ZVdvcmtiZW5jaFdpbmRvdygpLmdldFNoZWxsKCk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkvLyBpZ25vcmUKCQkJfQoJCQlpZiAoc2hlbGwyID09IG51bGwpCgkJCQlzaGVsbDIgPSBEaXNwbGF5LmdldERlZmF1bHQoKS5nZXRBY3RpdmVTaGVsbCgpOwoJCX0KCQlmaW5hbCBTaGVsbCBzaGVsbCA9IHNoZWxsMjsKCQkKCQkvLyBnZXQgYSB2YWxpZCBNb2R1bGVBcnRpZmFjdCB0aGF0IHdlIGNhbiB1c2UgZm9yIGxhdW5jaGluZwoJCS8vIFRPRE8gVGhlIE1vZHVsZUFydGlmYWN0Q29tcG9zaXRlIHNob3VsZCBiZSBwYXJ0IG9mIHRoZSBSdW5PblNlcnZlcldpemFyZAoJCWZpbmFsIElNb2R1bGVBcnRpZmFjdCBtb2R1bGVBcnRpZmFjdDsKCQlpZiAobW9kdWxlQXJ0aWZhY3RzLmxlbmd0aCA+IDEpIHsKCQkJTW9kdWxlQXJ0aWZhY3RDb21wb3NpdGUgYXJ0aWZhY3RDb21wb3NpdGUgPSBuZXcgTW9kdWxlQXJ0aWZhY3RDb21wb3NpdGUoc2hlbGwsIG1vZHVsZUFydGlmYWN0cywgbGF1bmNoTW9kZSk7CgkJCWlmIChhcnRpZmFjdENvbXBvc2l0ZS5vcGVuKCkgPT0gV2luZG93LkNBTkNFTCkKCQkJCXJldHVybjsKCQkJCgkJCW1vZHVsZUFydGlmYWN0ID0gYXJ0aWZhY3RDb21wb3NpdGUuZ2V0U2VsZWN0aW9uKCk7CgkJfSBlbHNlCgkJCW1vZHVsZUFydGlmYWN0ID0gbW9kdWxlQXJ0aWZhY3RzWzBdOwoJCQoJCWlmIChtb2R1bGVBcnRpZmFjdC5nZXRNb2R1bGUoKSA9PSBudWxsKSB7IC8vIDE0OTQyNQoJCQlFY2xpcHNlVXRpbC5vcGVuRXJyb3IoTWVzc2FnZXMuZXJyb3JOb01vZHVsZXMpOwoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJNb2R1bGUgYXJ0aWZhY3Qgbm90IGNvbnRhaW5lZCBpbiBhIG1vZHVsZSIpOwoJCQlyZXR1cm47CgkJfQoJCWZpbmFsIElNb2R1bGUgbW9kdWxlID0gbW9kdWxlQXJ0aWZhY3QuZ2V0TW9kdWxlKCk7CgkJCgkJLy8gY2hlY2sgZm9yIHNlcnZlcnMgd2l0aCB0aGUgZ2l2ZW4gc3RhcnQgbW9kZQoJCUlTZXJ2ZXJbXSBzZXJ2ZXJzID0gU2VydmVyQ29yZS5nZXRTZXJ2ZXJzKCk7CgkJYm9vbGVhbiBmb3VuZCA9IGZhbHNlOwoJCWlmIChzZXJ2ZXJzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBzZXJ2ZXJzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplICYmICFmb3VuZDsgaSsrKSB7CgkJCQlpZiAoU2VydmVyVUlQbHVnaW4uaXNDb21wYXRpYmxlV2l0aExhdW5jaE1vZGUoc2VydmVyc1tpXSwgbGF1bmNoTW9kZSkpIHsKCQkJCQl0cnkgewoJCQkJCQlJTW9kdWxlW10gcGFyZW50cyA9IHNlcnZlcnNbaV0uZ2V0Um9vdE1vZHVsZXMobW9kdWxlLCBudWxsKTsKCQkJCQkJaWYgKHBhcmVudHMgIT0gbnVsbCAmJiBwYXJlbnRzLmxlbmd0aCA+IDApCgkJCQkJCQlmb3VuZCA9IHRydWU7CgkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJLy8gaWdub3JlCgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCQoJCWlmICghZm91bmQpIHsKCQkJLy8gbm8gZXhpc3Rpbmcgc2VydmVyIHN1cHBvcnRzIHRoZSBwcm9qZWN0IGFuZCBzdGFydCBtb2RlIQoJCQkvLyBjaGVjayBpZiB0aGVyZSBtaWdodCBiZSBhbm90aGVyIG9uZSB0aGF0IGNhbiBiZSBjcmVhdGVkCgkJCUlTZXJ2ZXJUeXBlW10gc2VydmVyVHlwZXMgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlclR5cGVzKCk7CgkJCWlmIChzZXJ2ZXJUeXBlcyAhPSBudWxsKSB7CgkJCQlpbnQgc2l6ZSA9IHNlcnZlclR5cGVzLmxlbmd0aDsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZSAmJiAhZm91bmQ7IGkrKykgewoJCQkJCUlTZXJ2ZXJUeXBlIHR5cGUgPSBzZXJ2ZXJUeXBlc1tpXTsKCQkJCQlJTW9kdWxlVHlwZVtdIG1vZHVsZVR5cGVzID0gdHlwZS5nZXRSdW50aW1lVHlwZSgpLmdldE1vZHVsZVR5cGVzKCk7CgkJCQkJaWYgKHR5cGUuc3VwcG9ydHNMYXVuY2hNb2RlKGxhdW5jaE1vZGUpICYmIFNlcnZlclV0aWwuaXNTdXBwb3J0ZWRNb2R1bGUobW9kdWxlVHlwZXMsIG1vZHVsZS5nZXRNb2R1bGVUeXBlKCkpKSB7CgkJCQkJCWZvdW5kID0gdHJ1ZTsKCQkJCQl9CgkJCQl9CgkJCX0KCQkJaWYgKCFmb3VuZCkgewoJCQkJRWNsaXBzZVV0aWwub3BlbkVycm9yKE1lc3NhZ2VzLmVycm9yTm9TZXJ2ZXIpOwoJCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiTm8gc2VydmVyIGZvciBzdGFydCBtb2RlIik7CgkJCQlyZXR1cm47CgkJCX0KCQl9CgkJCgkJaWYgKCFTZXJ2ZXJVSVBsdWdpbi5zYXZlRWRpdG9ycygpKQoJCQlyZXR1cm47CgkJCgkJdGFza3NBbmRDbGllbnRTaG93biA9IGZhbHNlOwoJCUlTZXJ2ZXIgc2VydmVyMiA9IG51bGw7CgkJY2xpZW50ID0gbnVsbDsKCQlsYXVuY2hhYmxlQWRhcHRlciA9IG51bGw7CgkJdHJ5IHsKCQkJSVByb2dyZXNzTW9uaXRvciBtb25pdG9yID0gbmV3IE51bGxQcm9ncmVzc01vbml0b3IoKTsKCQkJc2VydmVyMiA9IGdldFNlcnZlcihtb2R1bGUsIG1vZHVsZUFydGlmYWN0LCBtb25pdG9yKTsKCQkJaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKQoJCQkJcmV0dXJuOwoJCQkKCQkJaWYgKHNlcnZlcjIgIT0gbnVsbCkgewoJCQkJSUZvbGRlciBmb2xkZXIgPSBzZXJ2ZXIyLmdldFNlcnZlckNvbmZpZ3VyYXRpb24oKTsKCQkJCWlmIChmb2xkZXIgIT0gbnVsbCAmJiBmb2xkZXIuZ2V0UHJvamVjdCgpICE9IG51bGwgJiYgIWZvbGRlci5nZXRQcm9qZWN0KCkuaXNPcGVuKCkpCgkJCQkJZm9sZGVyLmdldFByb2plY3QoKS5vcGVuKG1vbml0b3IpOwoJCQl9CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQlFY2xpcHNlVXRpbC5vcGVuRXJyb3Ioc2hlbGwsIGNlLmdldExvY2FsaXplZE1lc3NhZ2UoKSk7CgkJCXJldHVybjsKCQl9CgkJZmluYWwgSVNlcnZlciBzZXJ2ZXIgPSBzZXJ2ZXIyOwoJCS8vaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKQoJCS8vCXJldHVybjsKCQkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJTZXJ2ZXI6ICIgKyBzZXJ2ZXIpOwoJCQoJCWlmIChzZXJ2ZXIgPT0gbnVsbCkgewoJCQlFY2xpcHNlVXRpbC5vcGVuRXJyb3IoTWVzc2FnZXMuZXJyb3JOb1NlcnZlcik7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIk5vIHNlcnZlciBmb3VuZCIpOwoJCQlyZXR1cm47CgkJfQoJCQoJCWlmICghU2VydmVyVUlQbHVnaW4ucHJvbXB0SWZEaXJ0eShzaGVsbCwgc2VydmVyKSkKCQkJcmV0dXJuOwoJCQoJCWlmICghdGFza3NBbmRDbGllbnRTaG93bikgewoJCQlSdW5PblNlcnZlcldpemFyZCB3aXphcmQgPSBuZXcgUnVuT25TZXJ2ZXJXaXphcmQoc2VydmVyLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCk7CgkJCWlmICh3aXphcmQuc2hvdWxkQXBwZWFyKCkpIHsKCQkJCVdpemFyZERpYWxvZyBkaWFsb2cgPSBuZXcgV2l6YXJkRGlhbG9nKHNoZWxsLCB3aXphcmQpOwoJCQkJaWYgKGRpYWxvZy5vcGVuKCkgPT0gV2luZG93LkNBTkNFTCkKCQkJCQlyZXR1cm47CgkJCX0gZWxzZQoJCQkJd2l6YXJkLnBlcmZvcm1GaW5pc2goKTsKCQkJY2xpZW50ID0gd2l6YXJkLmdldFNlbGVjdGVkQ2xpZW50KCk7CgkJCWxhdW5jaGFibGVBZGFwdGVyID0gd2l6YXJkLmdldExhdW5jaGFibGVBZGFwdGVyKCk7CgkJfQoJCQkKCQkvLyBpZiB0aGVyZSBpcyBubyBjbGllbnQsIHVzZSBhIGR1bW15CgkJaWYgKGNsaWVudCA9PSBudWxsKXsJCQoJCQkJY2xpZW50ID0gbmV3IElDbGllbnQoKSB7CgkJCQkJcHVibGljIFN0cmluZyBnZXREZXNjcmlwdGlvbigpIHsKCQkJCQkJcmV0dXJuIE1lc3NhZ2VzLmNsaWVudERlZmF1bHREZXNjcmlwdGlvbjsKCQkJCQl9CgoJCQkJCXB1YmxpYyBTdHJpbmcgZ2V0SWQoKSB7CgkJCQkJCXJldHVybiAib3JnLmVjbGlwc2Uud3N0aC5zZXJ2ZXIudWkuY2xpZW50LmRlZmF1bHQiOwoJCQkJCX0KCgkJCQkJcHVibGljIFN0cmluZyBnZXROYW1lKCkgewoJCQkJCQlyZXR1cm4gTWVzc2FnZXMuY2xpZW50RGVmYXVsdE5hbWU7CgkJCQkJfQoKCQkJCQlwdWJsaWMgSVN0YXR1cyBsYXVuY2goSVNlcnZlciBzZXJ2ZXIzLCBPYmplY3QgbGF1bmNoYWJsZTIsIFN0cmluZyBsYXVuY2hNb2RlMywgSUxhdW5jaCBsYXVuY2gpIHsKCQkJCQkJcmV0dXJuIFN0YXR1cy5PS19TVEFUVVM7CgkJCQkJfQoKCQkJCQlwdWJsaWMgYm9vbGVhbiBzdXBwb3J0cyhJU2VydmVyIHNlcnZlcjMsIE9iamVjdCBsYXVuY2hhYmxlMiwgU3RyaW5nIGxhdW5jaE1vZGUzKSB7CgkJCQkJCXJldHVybiB0cnVlOwoJCQkJCX0KCQkJCX07CgkJfQkJCgkJCgkJaWYgKG1vZHVsZUFydGlmYWN0IGluc3RhbmNlb2YgTW9kdWxlQXJ0aWZhY3REZWxlZ2F0ZSkgewoJCQlib29sZWFuIGNhbkxvYWQgPSBmYWxzZTsKCQkJdHJ5IHsKCQkJCUNsYXNzIGMgPSBDbGFzcy5mb3JOYW1lKG1vZHVsZUFydGlmYWN0LmdldENsYXNzKCkuZ2V0TmFtZSgpKTsKCQkJCWlmIChjLm5ld0luc3RhbmNlKCkgIT0gbnVsbCkKCQkJCQljYW5Mb2FkID0gdHJ1ZTsKCQkJfSBjYXRjaCAoVGhyb3dhYmxlIHQpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLldBUk5JTkcsICJDb3VsZCBub3QgbG9hZCBtb2R1bGUgYXJ0aWZhY3QgZGVsZWdhdGUgY2xhc3MsIHN3aXRjaGluZyB0byBiYWNrdXAiKTsKCQkJfQoJCQlpZiAoY2FuTG9hZCkgewoJCQkJdHJ5IHsKCQkJCQlJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IgPSBuZXcgTnVsbFByb2dyZXNzTW9uaXRvcigpOwoJCQkJCUlMYXVuY2hDb25maWd1cmF0aW9uIGNvbmZpZyA9IGdldExhdW5jaENvbmZpZ3VyYXRpb24oc2VydmVyLCAoTW9kdWxlQXJ0aWZhY3REZWxlZ2F0ZSkgbW9kdWxlQXJ0aWZhY3QsIGxhdW5jaGFibGVBZGFwdGVyLCBjbGllbnQsIG1vbml0b3IpOwoJCQkJCWNvbmZpZy5sYXVuY2gobGF1bmNoTW9kZSwgbW9uaXRvcik7CgkJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IGxhdW5jaCBSdW4gb24gU2VydmVyIiwgY2UpOwoJCQkJfQoJCQkJcmV0dXJuOwoJCQl9CgkJfQoJCQoJCVRocmVhZCB0aHJlYWQgPSBuZXcgVGhyZWFkKCJSdW4gb24gU2VydmVyIikgewoJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJSZWFkeSB0byBsYXVuY2giKTsKCQkJCQoJCQkJLy8gc3RhcnQgc2VydmVyIGlmIGl0J3Mgbm90IGFscmVhZHkgc3RhcnRlZAoJCQkJLy8gYW5kIGN1ZSB0aGUgY2xpZW50IHRvIHN0YXJ0CgkJCQlJTW9kdWxlW10gbW9kdWxlcyA9IG5ldyBJTW9kdWxlW10geyBtb2R1bGUgfTsgLy8gVE9ETzogZ2V0IHBhcmVudCBoaWVyYXJjaHkgY29ycmVjdAoJCQkJaW50IHN0YXRlID0gc2VydmVyLmdldFNlcnZlclN0YXRlKCk7CgkJCQlpZiAoc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVEFSVElORykgewoJCQkJCUxhdW5jaENsaWVudEpvYiBjbGllbnRKb2IgPSBuZXcgTGF1bmNoQ2xpZW50Sm9iKHNlcnZlciwgbW9kdWxlcywgbGF1bmNoTW9kZSwgbW9kdWxlQXJ0aWZhY3QsIGxhdW5jaGFibGVBZGFwdGVyLCBjbGllbnQpOwoJCQkJCWNsaWVudEpvYi5zY2hlZHVsZSgpOwoJCQkJfSBlbHNlIGlmIChzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQpIHsKCQkJCQlib29sZWFuIHJlc3RhcnQgPSBmYWxzZTsKCQkJCQlTdHJpbmcgbW9kZSA9IHNlcnZlci5nZXRNb2RlKCk7CgkJCQkJSUJyZWFrcG9pbnRNYW5hZ2VyIGJyZWFrcG9pbnRNYW5hZ2VyID0gRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldEJyZWFrcG9pbnRNYW5hZ2VyKCk7CgkJCQkJYm9vbGVhbiBkaXNhYmxlZEJyZWFrcG9pbnRzID0gZmFsc2U7CgkJCQkJCgkJCQkJaWYgKHNlcnZlci5nZXRTZXJ2ZXJSZXN0YXJ0U3RhdGUoKSkgewoJCQkJCQlpbnQgcmVzdWx0ID0gb3BlblJlc3RhcnREaWFsb2coc2hlbGwpOwoJCQkJCQlpZiAocmVzdWx0ID09IDApIHsKCQkJCQkJCWxhdW5jaE1vZGUgPSBtb2RlOwoJCQkJCQkJcmVzdGFydCA9IHRydWU7CgkJCQkJCX0gZWxzZSBpZiAocmVzdWx0ID09IDkpIC8vIGNhbmNlbAoJCQkJCQkJcmV0dXJuOwoJCQkJCX0KCQkJCQlpZiAoIXJlc3RhcnQpIHsKCQkJCQkJaWYgKCFJTGF1bmNoTWFuYWdlci5SVU5fTU9ERS5lcXVhbHMobW9kZSkgJiYgSUxhdW5jaE1hbmFnZXIuUlVOX01PREUuZXF1YWxzKGxhdW5jaE1vZGUpKSB7CgkJCQkJCQlib29sZWFuIGJyZWFrcG9pbnRzT3B0aW9uID0gZmFsc2U7CgkJCQkJCQlpZiAoYnJlYWtwb2ludE1hbmFnZXIuaXNFbmFibGVkKCkgJiYgSUxhdW5jaE1hbmFnZXIuREVCVUdfTU9ERS5lcXVhbHMobW9kZSkpCgkJCQkJCQkJYnJlYWtwb2ludHNPcHRpb24gPSB0cnVlOwoJCQkJCQkJaW50IHJlc3VsdCA9IG9wZW5PcHRpb25zRGlhbG9nKHNoZWxsLCBNZXNzYWdlcy53aXpSdW5PblNlcnZlclRpdGxlLCBNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ1J1biwgYnJlYWtwb2ludHNPcHRpb24pOwoJCQkJCQkJaWYgKHJlc3VsdCA9PSAwKQoJCQkJCQkJCXJlc3RhcnQgPSB0cnVlOwoJCQkJCQkJZWxzZSBpZiAocmVzdWx0ID09IDEpIHsKCQkJCQkJCQlicmVha3BvaW50TWFuYWdlci5zZXRFbmFibGVkKGZhbHNlKTsKCQkJCQkJCQlkaXNhYmxlZEJyZWFrcG9pbnRzID0gdHJ1ZTsKCQkJCQkJCQlsYXVuY2hNb2RlID0gbW9kZTsKCQkJCQkJCX0gZWxzZSBpZiAocmVzdWx0ID09IDIpCgkJCQkJCQkJbGF1bmNoTW9kZSA9IG1vZGU7CgkJCQkJCQllbHNlIC8vIHJlc3VsdCA9PSA5IC8vIGNhbmNlbAoJCQkJCQkJCXJldHVybjsKCQkJCQkJfSBlbHNlIGlmICghSUxhdW5jaE1hbmFnZXIuREVCVUdfTU9ERS5lcXVhbHMobW9kZSkgJiYgSUxhdW5jaE1hbmFnZXIuREVCVUdfTU9ERS5lcXVhbHMobGF1bmNoTW9kZSkpIHsKCQkJCQkJCWludCByZXN1bHQgPSBvcGVuT3B0aW9uc0RpYWxvZyhzaGVsbCwgTWVzc2FnZXMud2l6RGVidWdPblNlcnZlclRpdGxlLCBNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0RlYnVnLCBmYWxzZSk7CgkJCQkJCQlpZiAocmVzdWx0ID09IDApCgkJCQkJCQkJcmVzdGFydCA9IHRydWU7CgkJCQkJCQllbHNlIGlmIChyZXN1bHQgPT0gMSkKCQkJCQkJCQlsYXVuY2hNb2RlID0gbW9kZTsKCQkJCQkJCWVsc2UgLy8gcmVzdWx0ID09IDkgLy8gY2FuY2VsCgkJCQkJCQkJcmV0dXJuOwoJCQkJCQl9IGVsc2UgaWYgKCFJTGF1bmNoTWFuYWdlci5QUk9GSUxFX01PREUuZXF1YWxzKG1vZGUpICYmIElMYXVuY2hNYW5hZ2VyLlBST0ZJTEVfTU9ERS5lcXVhbHMobGF1bmNoTW9kZSkpIHsKCQkJCQkJCWJvb2xlYW4gYnJlYWtwb2ludHNPcHRpb24gPSBmYWxzZTsKCQkJCQkJCWlmIChicmVha3BvaW50TWFuYWdlci5pc0VuYWJsZWQoKSAmJiBJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLmVxdWFscyhtb2RlKSkKCQkJCQkJCQlicmVha3BvaW50c09wdGlvbiA9IHRydWU7CgkJCQkJCQlpbnQgcmVzdWx0ID0gb3Blbk9wdGlvbnNEaWFsb2coc2hlbGwsIE1lc3NhZ2VzLndpelByb2ZpbGVPblNlcnZlclRpdGxlLCBNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ1Byb2ZpbGUsIGJyZWFrcG9pbnRzT3B0aW9uKTsKCQkJCQkJCWlmIChyZXN1bHQgPT0gMCkKCQkJCQkJCQlyZXN0YXJ0ID0gdHJ1ZTsKCQkJCQkJCWVsc2UgaWYgKHJlc3VsdCA9PSAxKSB7CgkJCQkJCQkJYnJlYWtwb2ludE1hbmFnZXIuc2V0RW5hYmxlZChmYWxzZSk7CgkJCQkJCQkJZGlzYWJsZWRCcmVha3BvaW50cyA9IHRydWU7CgkJCQkJCQkJbGF1bmNoTW9kZSA9IG1vZGU7CgkJCQkJCQl9IGVsc2UgaWYgKHJlc3VsdCA9PSAyKQoJCQkJCQkJCWxhdW5jaE1vZGUgPSBtb2RlOwoJCQkJCQkJZWxzZSAvLyByZXN1bHQgPT0gOSAvLyBjYW5jZWwKCQkJCQkJCQlyZXR1cm47CgkJCQkJCX0KCQkJCQkJCgkJCQkJCWlmIChJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLmVxdWFscyhsYXVuY2hNb2RlKSkgewoJCQkJCQkJaWYgKCFicmVha3BvaW50TWFuYWdlci5pc0VuYWJsZWQoKSAmJiAhZGlzYWJsZWRCcmVha3BvaW50cykgewoJCQkJCQkJCWludCByZXN1bHQgPSBvcGVuQnJlYWtwb2ludERpYWxvZyhzaGVsbCk7CgkJCQkJCQkJaWYgKHJlc3VsdCA9PSAwKQoJCQkJCQkJCQlicmVha3BvaW50TWFuYWdlci5zZXRFbmFibGVkKHRydWUpOwoJCQkJCQkJCWVsc2UgaWYgKHJlc3VsdCA9PSAxKSB7CgkJCQkJCQkJCS8vIGlnbm9yZQoJCQkJCQkJCX0gZWxzZSAvLyByZXN1bHQgPT0gMgoJCQkJCQkJCQlyZXR1cm47CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQkJCgkJCQkJUHVibGlzaFNlcnZlckpvYiBwdWJsaXNoSm9iID0gbmV3IFB1Ymxpc2hTZXJ2ZXJKb2Ioc2VydmVyLCBJU2VydmVyLlBVQkxJU0hfSU5DUkVNRU5UQUwsIGZhbHNlKTsKCQkJCQlMYXVuY2hDbGllbnRKb2IgY2xpZW50Sm9iID0gbmV3IExhdW5jaENsaWVudEpvYihzZXJ2ZXIsIG1vZHVsZXMsIGxhdW5jaE1vZGUsIG1vZHVsZUFydGlmYWN0LCBsYXVuY2hhYmxlQWRhcHRlciwgY2xpZW50KTsKCQkJCQlwdWJsaXNoSm9iLnNldE5leHRKb2IoY2xpZW50Sm9iKTsKCQkJCQkKCQkJCQlpZiAocmVzdGFydCkgewoJCQkJCQlSZXN0YXJ0U2VydmVySm9iIHJlc3RhcnRKb2IgPSBuZXcgUmVzdGFydFNlcnZlckpvYihzZXJ2ZXIsIGxhdW5jaE1vZGUpOwoJCQkJCQlyZXN0YXJ0Sm9iLnNldE5leHRKb2IocHVibGlzaEpvYik7CgkJCQkJCXJlc3RhcnRKb2Iuc2NoZWR1bGUoKTsKCQkJCQl9IGVsc2UKCQkJCQkJcHVibGlzaEpvYi5zY2hlZHVsZSgpOwoJCQkJfSBlbHNlIGlmIChzdGF0ZSAhPSBJU2VydmVyLlNUQVRFX1NUT1BQSU5HKSB7CgkJCQkJUHVibGlzaFNlcnZlckpvYiBwdWJsaXNoSm9iID0gbmV3IFB1Ymxpc2hTZXJ2ZXJKb2Ioc2VydmVyKTsKCQkJCQlTdGFydFNlcnZlckpvYiBzdGFydFNlcnZlckpvYiA9IG5ldyBTdGFydFNlcnZlckpvYihzZXJ2ZXIsIGxhdW5jaE1vZGUpOwoJCQkJCUxhdW5jaENsaWVudEpvYiBjbGllbnRKb2IgPSBuZXcgTGF1bmNoQ2xpZW50Sm9iKHNlcnZlciwgbW9kdWxlcywgbGF1bmNoTW9kZSwgbW9kdWxlQXJ0aWZhY3QsIGxhdW5jaGFibGVBZGFwdGVyLCBjbGllbnQpOwoJCQkJCQoJCQkJCWlmICgoKFNlcnZlclR5cGUpc2VydmVyLmdldFNlcnZlclR5cGUoKSkuc3RhcnRCZWZvcmVQdWJsaXNoKCkpIHsKCQkJCQkJc3RhcnRTZXJ2ZXJKb2Iuc2V0TmV4dEpvYihwdWJsaXNoSm9iKTsKCQkJCQkJcHVibGlzaEpvYi5zZXROZXh0Sm9iKGNsaWVudEpvYik7CgkJCQkJCXN0YXJ0U2VydmVySm9iLnNjaGVkdWxlKCk7CgkJCQkJfSBlbHNlIHsKCQkJCQkJcHVibGlzaEpvYi5zZXROZXh0Sm9iKHN0YXJ0U2VydmVySm9iKTsKCQkJCQkJc3RhcnRTZXJ2ZXJKb2Iuc2V0TmV4dEpvYihjbGllbnRKb2IpOwoJCQkJCQlwdWJsaXNoSm9iLnNjaGVkdWxlKCk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfTsKCQl0aHJlYWQuc2V0RGFlbW9uKHRydWUpOwoJCXRocmVhZC5zdGFydCgpOwoJfQoKCXByb3RlY3RlZCB2b2lkIHNldHVwTGF1bmNoQ29uZmlndXJhdGlvbihJTGF1bmNoQ29uZmlndXJhdGlvbldvcmtpbmdDb3B5IGNvbmZpZywgSVNlcnZlciBzZXJ2ZXIsIE1vZHVsZUFydGlmYWN0RGVsZWdhdGUgbW9kdWxlQXJ0aWZhY3QsIElMYXVuY2hhYmxlQWRhcHRlciBsYXVuY2hhYmxlQWRhcHRlciwgSUNsaWVudCBjbGllbnQpIHsKCQlTdHJpbmcgbGF1bmNoTmFtZSA9IE5MUy5iaW5kKE1lc3NhZ2VzLnJ1bk9uU2VydmVyTGF1bmNoQ29uZmlnTmFtZSwgbW9kdWxlQXJ0aWZhY3QuZ2V0TmFtZSgpKTsKCQlsYXVuY2hOYW1lID0gZ2V0VmFsaWRMYXVuY2hDb25maWd1cmF0aW9uTmFtZShsYXVuY2hOYW1lKTsKCQlpZiAoIWxhdW5jaE5hbWUuZXF1YWxzKGNvbmZpZy5nZXROYW1lKCkpKSB7CgkJCUlMYXVuY2hNYW5hZ2VyIGxhdW5jaE1hbmFnZXIgPSBEZWJ1Z1BsdWdpbi5nZXREZWZhdWx0KCkuZ2V0TGF1bmNoTWFuYWdlcigpOwoJCQlsYXVuY2hOYW1lID0gbGF1bmNoTWFuYWdlci5nZW5lcmF0ZVVuaXF1ZUxhdW5jaENvbmZpZ3VyYXRpb25OYW1lRnJvbShsYXVuY2hOYW1lKTsKCQkJY29uZmlnLnJlbmFtZShsYXVuY2hOYW1lKTsKCQl9CgkJCgkJY29uZmlnLnNldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX1NFUlZFUl9JRCwgc2VydmVyLmdldElkKCkpOwoJCWNvbmZpZy5zZXRBdHRyaWJ1dGUoUnVuT25TZXJ2ZXJMYXVuY2hDb25maWd1cmF0aW9uRGVsZWdhdGUuQVRUUl9NT0RVTEVfQVJUSUZBQ1QsIG1vZHVsZUFydGlmYWN0LnNlcmlhbGl6ZSgpKTsKCQljb25maWcuc2V0QXR0cmlidXRlKFJ1bk9uU2VydmVyTGF1bmNoQ29uZmlndXJhdGlvbkRlbGVnYXRlLkFUVFJfTU9EVUxFX0FSVElGQUNUX0NMQVNTLCBtb2R1bGVBcnRpZmFjdC5nZXRDbGFzcygpLmdldE5hbWUoKSk7CgkJY29uZmlnLnNldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX0xBVU5DSEFCTEVfQURBUFRFUl9JRCwgbGF1bmNoYWJsZUFkYXB0ZXIuZ2V0SWQoKSk7CgkJY29uZmlnLnNldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX0NMSUVOVF9JRCwgY2xpZW50LmdldElkKCkpOwoJfQoKCXByb3RlY3RlZCBJTGF1bmNoQ29uZmlndXJhdGlvbiBnZXRMYXVuY2hDb25maWd1cmF0aW9uKElTZXJ2ZXIgc2VydmVyLCBNb2R1bGVBcnRpZmFjdERlbGVnYXRlIG1vZHVsZUFydGlmYWN0LCBJTGF1bmNoYWJsZUFkYXB0ZXIgbGF1bmNoYWJsZUFkYXB0ZXIyLCBJQ2xpZW50IGNsaWVudDIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCVN0cmluZyBzZXJ2ZXJJZCA9IHNlcnZlci5nZXRJZCgpOwoJCUlMYXVuY2hNYW5hZ2VyIGxhdW5jaE1hbmFnZXIgPSBEZWJ1Z1BsdWdpbi5nZXREZWZhdWx0KCkuZ2V0TGF1bmNoTWFuYWdlcigpOwoJCUlMYXVuY2hDb25maWd1cmF0aW9uVHlwZSBsYXVuY2hDb25maWdUeXBlID0gbGF1bmNoTWFuYWdlci5nZXRMYXVuY2hDb25maWd1cmF0aW9uVHlwZSgib3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5sYXVuY2hDb25maWd1cmF0aW9uVHlwZSIpOwoJCUlMYXVuY2hDb25maWd1cmF0aW9uW10gbGF1bmNoQ29uZmlncyA9IG51bGw7CgkJdHJ5IHsKCQkJbGF1bmNoQ29uZmlncyA9IGxhdW5jaE1hbmFnZXIuZ2V0TGF1bmNoQ29uZmlndXJhdGlvbnMobGF1bmNoQ29uZmlnVHlwZSk7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCS8vIGlnbm9yZQoJCX0KCQkKCQlpZiAobGF1bmNoQ29uZmlncyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gbGF1bmNoQ29uZmlncy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlMaXN0IGxpc3QgPSBsYXVuY2hDb25maWdzW2ldLmdldEF0dHJpYnV0ZShJRGVidWdVSUNvbnN0YW50cy5BVFRSX0ZBVk9SSVRFX0dST1VQUywgKExpc3QpbnVsbCk7CgkJCQlpZiAobGlzdCA9PSBudWxsIHx8IGxpc3QuaXNFbXB0eSgpKSB7CgkJCQkJdHJ5IHsKCQkJCQkJU3RyaW5nIHNlcnZlcklkMiA9IGxhdW5jaENvbmZpZ3NbaV0uZ2V0QXR0cmlidXRlKFJ1bk9uU2VydmVyTGF1bmNoQ29uZmlndXJhdGlvbkRlbGVnYXRlLkFUVFJfU0VSVkVSX0lELCAoU3RyaW5nKSBudWxsKTsKCQkJCQkJaWYgKHNlcnZlcklkLmVxdWFscyhzZXJ2ZXJJZDIpKSB7CgkJCQkJCQlmaW5hbCBJTGF1bmNoQ29uZmlndXJhdGlvbldvcmtpbmdDb3B5IHdjID0gbGF1bmNoQ29uZmlnc1tpXS5nZXRXb3JraW5nQ29weSgpOwoJCQkJCQkJc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKHdjLCBzZXJ2ZXIsIG1vZHVsZUFydGlmYWN0LCBsYXVuY2hhYmxlQWRhcHRlcjIsIGNsaWVudDIpOwoJCQkJCQkJaWYgKHdjLmlzRGlydHkoKSkgewoJCQkJCQkJCXRyeSB7CgkJCQkJCQkJCXJldHVybiB3Yy5kb1NhdmUoKTsKCQkJCQkJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNvbmZpZ3VyaW5nIGxhdW5jaCIsIGNlKTsKCQkJCQkJCQl9CgkJCQkJCQl9CgkJCQkJCQlyZXR1cm4gbGF1bmNoQ29uZmlnc1tpXTsKCQkJCQkJfQoJCQkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjb25maWd1cmluZyBsYXVuY2giLCBlKTsKCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkJCgkJLy8gY3JlYXRlIGEgbmV3IGxhdW5jaCBjb25maWd1cmF0aW9uCgkJU3RyaW5nIGxhdW5jaE5hbWUgPSBOTFMuYmluZChNZXNzYWdlcy5ydW5PblNlcnZlckxhdW5jaENvbmZpZ05hbWUsIG1vZHVsZUFydGlmYWN0LmdldE5hbWUoKSk7CgkJbGF1bmNoTmFtZSA9IGdldFZhbGlkTGF1bmNoQ29uZmlndXJhdGlvbk5hbWUobGF1bmNoTmFtZSk7CgkJbGF1bmNoTmFtZSA9IGxhdW5jaE1hbmFnZXIuZ2VuZXJhdGVVbmlxdWVMYXVuY2hDb25maWd1cmF0aW9uTmFtZUZyb20obGF1bmNoTmFtZSk7IAoJCUlMYXVuY2hDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgd2MgPSBsYXVuY2hDb25maWdUeXBlLm5ld0luc3RhbmNlKG51bGwsIGxhdW5jaE5hbWUpOwoJCXdjLnNldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX1NFUlZFUl9JRCwgc2VydmVySWQpOwoJCXNldHVwTGF1bmNoQ29uZmlndXJhdGlvbih3Yywgc2VydmVyLCBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIyLCBjbGllbnQyKTsKCQlyZXR1cm4gd2MuZG9TYXZlKCk7Cgl9CgoJLy9wcm90ZWN0ZWQgc3RhdGljIGZpbmFsIGNoYXJbXSBJTlZBTElEX0NIQVJTID0gbmV3IGNoYXJbXSB7J1xcJywgJy8nLCAnOicsICcqJywgJz8nLCAnIicsICc8JywgJz4nLCAnfCcsICdcMCcsICdAJywgJyYnfTsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgY2hhcltdIElOVkFMSURfQ0hBUlMgPSBuZXcgY2hhcltdIHsnXFwnLCAnOicsICcqJywgJz8nLCAnIicsICc8JywgJz4nLCAnfCcsICdcMCcsICdAJywgJyYnfTsKCXByb3RlY3RlZCBTdHJpbmcgZ2V0VmFsaWRMYXVuY2hDb25maWd1cmF0aW9uTmFtZShTdHJpbmcgcykgewoJCWlmIChzID09IG51bGwgfHwgcy5sZW5ndGgoKSA9PSAwKQoJCQlyZXR1cm4gIjEiOwoJCWludCBzaXplID0gSU5WQUxJRF9DSEFSUy5sZW5ndGg7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJcyA9IHMucmVwbGFjZShJTlZBTElEX0NIQVJTW2ldLCAnXycpOwoJCX0KCQlyZXR1cm4gczsKCX0KCgkvKioKCSAqIE9wZW4gYW4gb3B0aW9ucyBkaWFsb2cuCgkgKiAKCSAqIEBwYXJhbSBzaGVsbAoJICogQHBhcmFtIHRpdGxlCgkgKiBAcGFyYW0gbWVzc2FnZQoJICogQHBhcmFtIGJyZWFrcG9pbnRzT3B0aW9uCgkgKiBAcmV0dXJuIGEgZGlhbG9nIHJldHVybiBjb25zdGFudAoJICovCglwcm90ZWN0ZWQgc3RhdGljIGludCBvcGVuT3B0aW9uc0RpYWxvZyhmaW5hbCBTaGVsbCBzaGVsbCwgZmluYWwgU3RyaW5nIHRpdGxlLCBmaW5hbCBTdHJpbmcgbWVzc2FnZSwgZmluYWwgYm9vbGVhbiBicmVha3BvaW50c09wdGlvbikgewoJCWlmIChicmVha3BvaW50c09wdGlvbikgewoJCQlpbnQgY3VycmVudCA9IFNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuZ2V0TGF1bmNoTW9kZTIoKTsKCQkJaWYgKGN1cnJlbnQgPT0gU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfUkVTVEFSVCkKCQkJCXJldHVybiAwOwoJCQllbHNlIGlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREUyX0RJU0FCTEVfQlJFQUtQT0lOVFMpCgkJCQlyZXR1cm4gMTsKCQkJZWxzZSBpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLkxBVU5DSF9NT0RFMl9DT05USU5VRSkKCQkJCXJldHVybiAyOwoJCX0gZWxzZSB7CgkJCWludCBjdXJyZW50ID0gU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5nZXRMYXVuY2hNb2RlKCk7CgkJCWlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREVfUkVTVEFSVCkKCQkJCXJldHVybiAwOwoJCQllbHNlIGlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREVfQ09OVElOVUUpCgkJCQlyZXR1cm4gMTsKCQl9CgkJZmluYWwgaW50W10gaSA9IG5ldyBpbnRbMV07CgkJc2hlbGwuZ2V0RGlzcGxheSgpLnN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJT3B0aW9uc01lc3NhZ2VEaWFsb2cgZGlhbG9nID0gbnVsbDsKCQkJCVN0cmluZ1tdIGl0ZW1zID0gbnVsbDsKCQkJCWlmIChicmVha3BvaW50c09wdGlvbikgewoJCQkJCWl0ZW1zID0gbmV3IFN0cmluZ1tdIHsKCQkJCQkJTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdSZXN0YXJ0LAoJCQkJCQlNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0JyZWFrcG9pbnRzLAoJCQkJCQlNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0NvbnRpbnVlCgkJCQkJfTsKCQkJCX0gZWxzZSB7CgkJCQkJaXRlbXMgPSBuZXcgU3RyaW5nW10gewoJCQkJCQlNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ1Jlc3RhcnQsCgkJCQkJCU1lc3NhZ2VzLmRpYWxvZ01vZGVXYXJuaW5nQ29udGludWUKCQkJCQl9OwoJCQkJfQoJCQkJCgkJCQlkaWFsb2cgPSBuZXcgT3B0aW9uc01lc3NhZ2VEaWFsb2coc2hlbGwsIHRpdGxlLCBtZXNzYWdlLCBpdGVtcyk7CgkJCQlpWzBdID0gZGlhbG9nLm9wZW4oKTsKCQkJCQoJCQkJaWYgKGRpYWxvZy5pc1JlbWVtYmVyKCkpIHsKCQkJCQlpZiAoYnJlYWtwb2ludHNPcHRpb24pIHsKCQkJCQkJaWYgKGlbMF0gPT0gMCkKCQkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0TGF1bmNoTW9kZTIoU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfUkVTVEFSVCk7CgkJCQkJCWVsc2UgaWYgKGlbMF0gPT0gMSkKCQkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0TGF1bmNoTW9kZTIoU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfRElTQUJMRV9CUkVBS1BPSU5UUyk7CgkJCQkJCWVsc2UgaWYgKGlbMF0gPT0gMikKCQkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0TGF1bmNoTW9kZTIoU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfQ09OVElOVUUpOwoJCQkJCX0gZWxzZSB7CgkJCQkJCWlmIChpWzBdID09IDApCgkJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldExhdW5jaE1vZGUoU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERV9SRVNUQVJUKTsKCQkJCQkJZWxzZSBpZiAoaVswXSA9PSAxKQoJCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRMYXVuY2hNb2RlKFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREVfQ09OVElOVUUpOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0pOwoJCXJldHVybiBpWzBdOwoJfQoKCS8qKgoJICogT3BlbiBhbiBvcHRpb25zIGRpYWxvZy4KCSAqIAoJICogQHBhcmFtIHNoZWxsCgkgKiBAcmV0dXJuIGEgZGlhbG9nIHJldHVybiBjb25zdGFudAoJICovCglwcm90ZWN0ZWQgc3RhdGljIGludCBvcGVuQnJlYWtwb2ludERpYWxvZyhmaW5hbCBTaGVsbCBzaGVsbCkgewoJCWludCBjdXJyZW50ID0gU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5nZXRFbmFibGVCcmVha3BvaW50cygpOwoJCWlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuRU5BQkxFX0JSRUFLUE9JTlRTX0FMV0FZUykKCQkJcmV0dXJuIDA7CgkJZWxzZSBpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLkVOQUJMRV9CUkVBS1BPSU5UU19ORVZFUikKCQkJcmV0dXJuIDE7CgkJCgkJZmluYWwgaW50W10gaSA9IG5ldyBpbnRbMV07CgkJc2hlbGwuZ2V0RGlzcGxheSgpLnN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJT3B0aW9uc01lc3NhZ2VEaWFsb2cgZGlhbG9nID0gbmV3IE9wdGlvbnNNZXNzYWdlRGlhbG9nKHNoZWxsLAoJCQkJCQlNZXNzYWdlcy53aXpEZWJ1Z09uU2VydmVyVGl0bGUsIE1lc3NhZ2VzLmRpYWxvZ0JyZWFrcG9pbnRzLCBuZXcgU3RyaW5nW10gewoJCQkJCQlNZXNzYWdlcy5kaWFsb2dCcmVha3BvaW50c1JlZW5hYmxlLCBNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0NvbnRpbnVlfSk7CgkJCQlpWzBdID0gZGlhbG9nLm9wZW4oKTsKCQkJCWlmIChkaWFsb2cuaXNSZW1lbWJlcigpKSB7CgkJCQkJaWYgKGlbMF0gPT0gMCkKCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRFbmFibGVCcmVha3BvaW50cyhTZXJ2ZXJVSVByZWZlcmVuY2VzLkVOQUJMRV9CUkVBS1BPSU5UU19BTFdBWVMpOwoJCQkJCWVsc2UgaWYgKGlbMF0gPT0gMSkKCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRFbmFibGVCcmVha3BvaW50cyhTZXJ2ZXJVSVByZWZlcmVuY2VzLkVOQUJMRV9CUkVBS1BPSU5UU19ORVZFUik7CgkJCQl9CgkJCX0KCQl9KTsKCQlyZXR1cm4gaVswXTsKCX0KCgkvKioKCSAqIE9wZW4gYSByZXN0YXJ0IG9wdGlvbnMgZGlhbG9nLgoJICogCgkgKiBAcGFyYW0gc2hlbGwKCSAqIEByZXR1cm4gYSBkaWFsb2cgcmV0dXJuIGNvbnN0YW50CgkgKi8KCXByb3RlY3RlZCBzdGF0aWMgaW50IG9wZW5SZXN0YXJ0RGlhbG9nKGZpbmFsIFNoZWxsIHNoZWxsKSB7CgkJaW50IGN1cnJlbnQgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLmdldFJlc3RhcnQoKTsKCQlpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLlJFU1RBUlRfQUxXQVlTKQoJCQlyZXR1cm4gMDsKCQllbHNlIGlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuUkVTVEFSVF9ORVZFUikKCQkJcmV0dXJuIDE7CgkJCgkJZmluYWwgaW50W10gaSA9IG5ldyBpbnRbMV07CgkJc2hlbGwuZ2V0RGlzcGxheSgpLnN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJT3B0aW9uc01lc3NhZ2VEaWFsb2cgZGlhbG9nID0gbmV3IE9wdGlvbnNNZXNzYWdlRGlhbG9nKHNoZWxsLAoJCQkJCQlNZXNzYWdlcy5kZWZhdWx0RGlhbG9nVGl0bGUsIE1lc3NhZ2VzLmRpYWxvZ1Jlc3RhcnQsIG5ldyBTdHJpbmdbXSB7CgkJCQkJCU1lc3NhZ2VzLmRpYWxvZ1Jlc3RhcnRSZXN0YXJ0LCBNZXNzYWdlcy5kaWFsb2dSZXN0YXJ0Q29udGludWV9KTsKCQkJCWlbMF0gPSBkaWFsb2cub3BlbigpOwoJCQkJaWYgKGRpYWxvZy5pc1JlbWVtYmVyKCkpIHsKCQkJCQlpZiAoaVswXSA9PSAwKQoJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldFJlc3RhcnQoU2VydmVyVUlQcmVmZXJlbmNlcy5SRVNUQVJUX0FMV0FZUyk7CgkJCQkJZWxzZSBpZiAoaVswXSA9PSAxKQoJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldFJlc3RhcnQoU2VydmVyVUlQcmVmZXJlbmNlcy5SRVNUQVJUX05FVkVSKTsKCQkJCX0KCQkJfQoJCX0pOwoJCXJldHVybiBpWzBdOwoJfQoKCS8qKgoJICogVGhlIGRlbGVnYXRpbmcgYWN0aW9uIGhhcyBiZWVuIHBlcmZvcm1lZC4gSW1wbGVtZW50CgkgKiB0aGlzIG1ldGhvZCB0byBkbyB0aGUgYWN0dWFsIHdvcmsuCgkgKgoJICogQHBhcmFtIGFjdGlvbiBhY3Rpb24gcHJveHkgdGhhdCBoYW5kbGVzIHRoZSBwcmVzZW50YXRpb24KCSAqIHBvcnRpb24gb2YgdGhlIHBsdWdpbiBhY3Rpb24KCSAqLwoJcHVibGljIHZvaWQgcnVuKElBY3Rpb24gYWN0aW9uKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiUnVubmluZyBvbiBTZXJ2ZXIuLi4iKTsKCQl0cnkgewoJCQlydW4oKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJSdW4gb24gU2VydmVyIEVycm9yIiwgZSk7CgkJfQoJfQoKCXByb3RlY3RlZCBib29sZWFuIGlzRW5hYmxlZCgpIHsKCQl0cnkgewoJCQlCb29sZWFuIGIgPSAoQm9vbGVhbikgZ2xvYmFsTGF1bmNoTW9kZS5nZXQoZ2V0TGF1bmNoTW9kZSgpKTsKCQkJcmV0dXJuIGIuYm9vbGVhblZhbHVlKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIHN0YXJ0IG1vZGUgdGhhdCB0aGUgc2VydmVyIHNob3VsZCB1c2UuCgkgKi8KCXByb3RlY3RlZCBTdHJpbmcgZ2V0TGF1bmNoTW9kZSgpIHsKCQlyZXR1cm4gbGF1bmNoTW9kZTsKCX0KCgkvKioKCSAqIFNldCB0aGUgbGF1bmNoIG1vZGUuCgkgKiAKCSAqIEBwYXJhbSBsYXVuY2hNb2RlIGEge0BsaW5rIElMYXVuY2hNYW5hZ2VyfSBsYXVuY2ggbW9kZQoJICovCglwdWJsaWMgdm9pZCBzZXRMYXVuY2hNb2RlKFN0cmluZyBsYXVuY2hNb2RlKSB7CgkJdGhpcy5sYXVuY2hNb2RlID0gbGF1bmNoTW9kZTsKCX0KCgkvKioKCSAqIERldGVybWluZSB3aGljaCBjbGllbnRzIGNhbiBhY3Qgb24gdGhlIGN1cnJlbnQgc2VsZWN0aW9uLgoJICoKCSAqIEBwYXJhbSBhY3Rpb24gYWN0aW9uIHByb3h5IHRoYXQgaGFuZGxlcyBwcmVzZW50YXRpb24KCSAqICAgIHBvcnRpb24gb2YgdGhlIHBsdWdpbiBhY3Rpb24KCSAqIEBwYXJhbSBzZWwgY3VycmVudCBzZWxlY3Rpb24gaW4gdGhlIGRlc2t0b3AKCSAqLwoJcHVibGljIHZvaWQgc2VsZWN0aW9uQ2hhbmdlZChJQWN0aW9uIGFjdGlvbiwgSVNlbGVjdGlvbiBzZWwpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICI+IHNlbGVjdGlvbkNoYW5nZWQiKTsKCQlzZWxlY3Rpb24gPSBudWxsOwoJCWxvbmcgdGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCWlmIChzZWwgPT0gbnVsbCB8fCBzZWwuaXNFbXB0eSgpIHx8ICEoc2VsIGluc3RhbmNlb2YgSVN0cnVjdHVyZWRTZWxlY3Rpb24pKSB7CgkJCWFjdGlvbi5zZXRFbmFibGVkKGZhbHNlKTsKCQkJZ2xvYmFsU2VsZWN0aW9uID0gbnVsbDsKCQkJcmV0dXJuOwoJCX0KCQkKCQlJU3RydWN0dXJlZFNlbGVjdGlvbiBzZWxlY3QgPSAoSVN0cnVjdHVyZWRTZWxlY3Rpb24pIHNlbDsKCQlJdGVyYXRvciBpdGVyYXRvciA9IHNlbGVjdC5pdGVyYXRvcigpOwoJCWlmIChpdGVyYXRvci5oYXNOZXh0KCkpCgkJCXNlbGVjdGlvbiA9IGl0ZXJhdG9yLm5leHQoKTsKCQlpZiAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7IC8vIG1vcmUgdGhhbiBvbmUgc2VsZWN0aW9uIChzaG91bGQgbmV2ZXIgaGFwcGVuKQoJCQlhY3Rpb24uc2V0RW5hYmxlZChmYWxzZSk7CgkJCXNlbGVjdGlvbiA9IG51bGw7CgkJCWdsb2JhbFNlbGVjdGlvbiA9IG51bGw7CgkJCXJldHVybjsKCQl9CgkJCgkJaWYgKHNlbGVjdGlvbiAhPSBnbG9iYWxTZWxlY3Rpb24pIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiU2VsZWN0aW9uOiAiICsgc2VsZWN0aW9uKTsKCQkJaWYgKHNlbGVjdGlvbiAhPSBudWxsKQkKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlNlbGVjdGlvbiB0eXBlOiAiICsgc2VsZWN0aW9uLmdldENsYXNzKCkuZ2V0TmFtZSgpKTsKCQkJZ2xvYmFsU2VsZWN0aW9uID0gc2VsZWN0aW9uOwoJCQlnbG9iYWxMYXVuY2hNb2RlID0gbmV3IEhhc2hNYXAoKTsKCQkJaWYgKCFTZXJ2ZXJQbHVnaW4uaGFzTW9kdWxlQXJ0aWZhY3QoZ2xvYmFsU2VsZWN0aW9uKSkgewoJCQkJYWN0aW9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCQkJcmV0dXJuOwoJCQl9CgkJCQoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJjaGVja2luZyBmb3IgbW9kdWxlIGFydGlmYWN0Iik7CgkJCS8vIFRPRE8gLSBtdWx0aXBsZSBtb2R1bGUgYXJ0aWZhY3RzCgkJCUlNb2R1bGVBcnRpZmFjdFtdIG1vZHVsZUFydGlmYWN0cyA9IFNlcnZlclBsdWdpbi5nZXRNb2R1bGVBcnRpZmFjdHMoZ2xvYmFsU2VsZWN0aW9uKTsKCQkJSU1vZHVsZUFydGlmYWN0IG1vZHVsZUFydGlmYWN0ID0gbnVsbDsKCQkJaWYgKG1vZHVsZUFydGlmYWN0cyAhPSBudWxsKQoJCQkJbW9kdWxlQXJ0aWZhY3QgPSBtb2R1bGVBcnRpZmFjdHNbMF07CgkJCQoJCQlJTW9kdWxlIG1vZHVsZSA9IG51bGw7CgkJCWlmIChtb2R1bGVBcnRpZmFjdCAhPSBudWxsKQoJCQkJbW9kdWxlID0gbW9kdWxlQXJ0aWZhY3QuZ2V0TW9kdWxlKCk7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIm1vZHVsZUFydGlmYWN0PSAiICsgbW9kdWxlQXJ0aWZhY3QgKyAiLCBtb2R1bGU9ICIgKyBtb2R1bGUpOwoJCQlpZiAobW9kdWxlICE9IG51bGwpCgkJCQlmaW5kR2xvYmFsTGF1bmNoTW9kZXMobW9kdWxlKTsKCQkJZWxzZSB7CgkJCQlnbG9iYWxMYXVuY2hNb2RlLnB1dChJTGF1bmNoTWFuYWdlci5SVU5fTU9ERSwgbmV3IEJvb2xlYW4odHJ1ZSkpOwoJCQkJZ2xvYmFsTGF1bmNoTW9kZS5wdXQoSUxhdW5jaE1hbmFnZXIuREVCVUdfTU9ERSwgbmV3IEJvb2xlYW4odHJ1ZSkpOwoJCQkJZ2xvYmFsTGF1bmNoTW9kZS5wdXQoSUxhdW5jaE1hbmFnZXIuUFJPRklMRV9NT0RFLCBuZXcgQm9vbGVhbih0cnVlKSk7CgkJCX0KCQl9CgkJCgkJYWN0aW9uLnNldEVuYWJsZWQoaXNFbmFibGVkKCkpOwoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIjwgc2VsZWN0aW9uQ2hhbmdlZCAiICsgKFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpIC0gdGltZSkpOwoJfQoKCS8qKgoJICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZXJlIGlzIGEgc2VydmVyIGZhY3RvcnkgYXZhaWxhYmxlIGZvciB0aGUgZ2l2ZW4gbW9kdWxlCgkgKiBhbmQgdGhlIHZhcmlvdXMgc3RhcnQgbW9kZXMuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpbmRHbG9iYWxMYXVuY2hNb2RlcyhJTW9kdWxlIG1vZHVsZSkgewoJCUlTZXJ2ZXJUeXBlW10gc2VydmVyVHlwZXMgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlclR5cGVzKCk7CgkJaWYgKHNlcnZlclR5cGVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBzZXJ2ZXJUeXBlcy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlJU2VydmVyVHlwZSB0eXBlID0gc2VydmVyVHlwZXNbaV07CgkJCQlpZiAoaXNWYWxpZFNlcnZlclR5cGUodHlwZSwgbW9kdWxlKSkgewoJCQkJCWZvciAoYnl0ZSBiID0gMDsgYiA8IGxhdW5jaE1vZGVzLmxlbmd0aDsgYisrKSB7CgkJCQkJCWlmICh0eXBlLnN1cHBvcnRzTGF1bmNoTW9kZShsYXVuY2hNb2Rlc1tiXSkpIHsKCQkJCQkJCWdsb2JhbExhdW5jaE1vZGUucHV0KGxhdW5jaE1vZGVzW2JdLCBuZXcgQm9vbGVhbih0cnVlKSk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGdpdmVuIHNlcnZlciB0eXBlIGNhbiBsYXVuY2ggdGhlIG1vZHVsZS4gCgkgKi8KCXByb3RlY3RlZCBib29sZWFuIGlzVmFsaWRTZXJ2ZXJUeXBlKElTZXJ2ZXJUeXBlIHR5cGUsIElNb2R1bGUgbW9kdWxlKSB7CgkJdHJ5IHsKCQkJSVJ1bnRpbWVUeXBlIHJ1bnRpbWVUeXBlID0gdHlwZS5nZXRSdW50aW1lVHlwZSgpOwoJCQlTZXJ2ZXJVdGlsLmlzU3VwcG9ydGVkTW9kdWxlKHJ1bnRpbWVUeXBlLmdldE1vZHVsZVR5cGVzKCksIG1vZHVsZS5nZXRNb2R1bGVUeXBlKCkpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCXJldHVybiBmYWxzZTsKCQl9CgkJcmV0dXJuIHRydWU7Cgl9Cn0=