LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA3IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuYWN0aW9uczsKCmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRm9sZGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLio7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuam9icy5Kb2I7CmltcG9ydCBvcmcuZWNsaXBzZS5kZWJ1Zy5jb3JlLio7CmltcG9ydCBvcmcuZWNsaXBzZS5kZWJ1Zy51aS5JRGVidWdVSUNvbnN0YW50czsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmFjdGlvbi5JQWN0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UuZGlhbG9ncy5FcnJvckRpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuSVNlbGVjdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuSVN0cnVjdHVyZWRTZWxlY3Rpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS53aW5kb3cuV2luZG93OwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2Uud2l6YXJkLldpemFyZERpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLklDbGllbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuSUxhdW5jaGFibGVBZGFwdGVyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLlB1Ymxpc2hTZXJ2ZXJKb2I7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuUmVzdGFydFNlcnZlckpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5TZXJ2ZXJQbHVnaW47CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuU2VydmVyVHlwZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5TdGFydFNlcnZlckpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5UcmFjZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC5Nb2R1bGVBcnRpZmFjdERlbGVnYXRlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC52aWV3ZXJzLk1vZHVsZUFydGlmYWN0Q29tcG9zaXRlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC53aXphcmQuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLm9zZ2kudXRpbC5OTFM7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5EaXNwbGF5OwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuU2hlbGw7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5JV29ya2JlbmNoV2luZG93OwppbXBvcnQgb3JnLmVjbGlwc2UudWkuSVdvcmtiZW5jaFdpbmRvd0FjdGlvbkRlbGVnYXRlOwovKioKICogU3VwcG9ydCBmb3Igc3RhcnRpbmcvc3RvcHBpbmcgc2VydmVyIGFuZCBjbGllbnRzIGZvciByZXNvdXJjZXMgcnVubmluZyBvbiBhIHNlcnZlci4KICovCnB1YmxpYyBjbGFzcyBSdW5PblNlcnZlckFjdGlvbkRlbGVnYXRlIGltcGxlbWVudHMgSVdvcmtiZW5jaFdpbmRvd0FjdGlvbkRlbGVnYXRlIHsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nW10gbGF1bmNoTW9kZXMgPSB7CgkJSUxhdW5jaE1hbmFnZXIuUlVOX01PREUsIElMYXVuY2hNYW5hZ2VyLkRFQlVHX01PREUsIElMYXVuY2hNYW5hZ2VyLlBST0ZJTEVfTU9ERSB9OwoKCXByb3RlY3RlZCBPYmplY3Qgc2VsZWN0aW9uOwoKCXByb3RlY3RlZCBJV29ya2JlbmNoV2luZG93IHdpbmRvdzsKCglwcm90ZWN0ZWQgc3RhdGljIE9iamVjdCBnbG9iYWxTZWxlY3Rpb247CgoJcHJvdGVjdGVkIHN0YXRpYyBNYXA8U3RyaW5nLCBCb29sZWFuPiBnbG9iYWxMYXVuY2hNb2RlOwoJcHJvdGVjdGVkIFN0cmluZyBsYXVuY2hNb2RlID0gSUxhdW5jaE1hbmFnZXIuUlVOX01PREU7CgoJcHJvdGVjdGVkIGJvb2xlYW4gdGFza3NBbmRDbGllbnRTaG93bjsKCglwcm90ZWN0ZWQgSUxhdW5jaGFibGVBZGFwdGVyIGxhdW5jaGFibGVBZGFwdGVyOwoJcHJvdGVjdGVkIElDbGllbnQgY2xpZW50OwoKCS8qKgoJICogUnVuT25TZXJ2ZXJBY3Rpb25EZWxlZ2F0ZSBjb25zdHJ1Y3RvciBjb21tZW50LgoJICovCglwdWJsaWMgUnVuT25TZXJ2ZXJBY3Rpb25EZWxlZ2F0ZSgpIHsKCQlzdXBlcigpOwoJfQoKCS8qKgoJICogRGlzcG9zZXMgdGhpcyBhY3Rpb24gZGVsZWdhdGUuICBUaGUgaW1wbGVtZW50b3Igc2hvdWxkIHVuaG9vayBhbnkgcmVmZXJlbmNlcwoJICogdG8gaXRzZWxmIHNvIHRoYXQgZ2FyYmFnZSBjb2xsZWN0aW9uIGNhbiBvY2N1ci4KCSAqLwoJcHVibGljIHZvaWQgZGlzcG9zZSgpIHsKCQl3aW5kb3cgPSBudWxsOwoJfQoKCS8qKgoJICogSW5pdGlhbGl6ZXMgdGhpcyBhY3Rpb24gZGVsZWdhdGUgd2l0aCB0aGUgd29ya2JlbmNoIHdpbmRvdyBpdCB3aWxsIHdvcmsgaW4uCgkgKgoJICogQHBhcmFtIG5ld1dpbmRvdyB0aGUgd2luZG93IHRoYXQgcHJvdmlkZXMgdGhlIGNvbnRleHQgZm9yIHRoaXMgZGVsZWdhdGUKCSAqLwoJcHVibGljIHZvaWQgaW5pdChJV29ya2JlbmNoV2luZG93IG5ld1dpbmRvdykgewoJCXdpbmRvdyA9IG5ld1dpbmRvdzsKCX0KCglwdWJsaWMgSVNlcnZlciBnZXRTZXJ2ZXIoSU1vZHVsZSBtb2R1bGUsIElNb2R1bGVBcnRpZmFjdCBtb2R1bGVBcnRpZmFjdCwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJSVNlcnZlciBzZXJ2ZXIgPSBTZXJ2ZXJDb3JlLmdldERlZmF1bHRTZXJ2ZXIobW9kdWxlKTsKCQkKCQkvLyBpZ25vcmUgcHJlZmVyZW5jZSBpZiB0aGUgc2VydmVyIGRvZXNuJ3Qgc3VwcG9ydCB0aGlzIG1vZGUuCgkJaWYgKHNlcnZlciAhPSBudWxsICYmICFTZXJ2ZXJVSVBsdWdpbi5pc0NvbXBhdGlibGVXaXRoTGF1bmNoTW9kZShzZXJ2ZXIsIGxhdW5jaE1vZGUpKQoJCQlzZXJ2ZXIgPSBudWxsOwoJCQoJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiAhU2VydmVyVXRpbC5jb250YWluc01vZHVsZShzZXJ2ZXIsIG1vZHVsZSwgbW9uaXRvcikpIHsKCQkJSVNlcnZlcldvcmtpbmdDb3B5IHdjID0gc2VydmVyLmNyZWF0ZVdvcmtpbmdDb3B5KCk7CgkJCXRyeSB7CgkJCQlTZXJ2ZXJVdGlsLm1vZGlmeU1vZHVsZXMod2MsIG5ldyBJTW9kdWxlW10geyBtb2R1bGUgfSwgbmV3IElNb2R1bGVbMF0sIG1vbml0b3IpOwoJCQkJd2Muc2F2ZShmYWxzZSwgbW9uaXRvcik7CgkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkNvdWxkIG5vdCBhZGQgbW9kdWxlIHRvIHNlcnZlciIsIGNlKTsKCQkJCXNlcnZlciA9IG51bGw7CgkJCX0KCQl9CgkJCgkJU2hlbGwgc2hlbGw7CgkJaWYgKHdpbmRvdyAhPSBudWxsKQoJCQlzaGVsbCA9IHdpbmRvdy5nZXRTaGVsbCgpOwoJCWVsc2UKCQkJc2hlbGwgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRJbnN0YW5jZSgpLmdldFdvcmtiZW5jaCgpLmdldEFjdGl2ZVdvcmtiZW5jaFdpbmRvdygpLmdldFNoZWxsKCk7CgkJCgkJaWYgKHNlcnZlciA9PSBudWxsKSB7CgkJCS8vIHRyeSB0aGUgZnVsbCB3aXphcmQKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiTGF1bmNoaW5nIHdpemFyZCIpOwoJCQlSdW5PblNlcnZlcldpemFyZCB3aXphcmQgPSBuZXcgUnVuT25TZXJ2ZXJXaXphcmQobW9kdWxlLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCk7CgkJCUNsb3NhYmxlV2l6YXJkRGlhbG9nIGRpYWxvZyA9IG5ldyBDbG9zYWJsZVdpemFyZERpYWxvZyhzaGVsbCwgd2l6YXJkKTsKCQkJaWYgKGRpYWxvZy5vcGVuKCkgPT0gV2luZG93LkNBTkNFTCkgewoJCQkJaWYgKG1vbml0b3IgIT0gbnVsbCkKCQkJCQltb25pdG9yLnNldENhbmNlbGVkKHRydWUpOwoJCQkJcmV0dXJuIG51bGw7CgkJCX0KCQkJCgkJCXRyeSB7CgkJCQlKb2IuZ2V0Sm9iTWFuYWdlcigpLmpvaW4oIm9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuZmFtaWx5IiwgbnVsbCk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5XQVJOSU5HLCAiRXJyb3Igd2FpdGluZyBmb3Igam9iIiwgZSk7CgkJCX0KCQkJc2VydmVyID0gd2l6YXJkLmdldFNlcnZlcigpOwoJCQlib29sZWFuIHByZWZlcnJlZCA9IHdpemFyZC5pc1ByZWZlcnJlZFNlcnZlcigpOwoJCQl0YXNrc0FuZENsaWVudFNob3duID0gdHJ1ZTsKCQkJY2xpZW50ID0gd2l6YXJkLmdldFNlbGVjdGVkQ2xpZW50KCk7CgkJCWxhdW5jaGFibGVBZGFwdGVyID0gd2l6YXJkLmdldExhdW5jaGFibGVBZGFwdGVyKCk7CgkJCQoJCQkvLyBzZXQgcHJlZmVycmVkIHNlcnZlciBpZiByZXF1ZXN0ZWQKCQkJaWYgKHNlcnZlciAhPSBudWxsICYmIHByZWZlcnJlZCkgewoJCQkJdHJ5IHsKCQkJCQlTZXJ2ZXJDb3JlLnNldERlZmF1bHRTZXJ2ZXIobW9kdWxlLCBzZXJ2ZXIsIG1vbml0b3IpOwoJCQkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQkJCVN0cmluZyBtZXNzYWdlID0gTWVzc2FnZXMuZXJyb3JDb3VsZE5vdFNhdmVQcmVmZXJlbmNlOwoJCQkJCUVycm9yRGlhbG9nLm9wZW5FcnJvcihzaGVsbCwgTWVzc2FnZXMuZXJyb3JEaWFsb2dUaXRsZSwgbWVzc2FnZSwgY2UuZ2V0U3RhdHVzKCkpOwoJCQkJfQoJCQl9CgkJfQoJCQoJCXRyeSB7CgkJCUpvYi5nZXRKb2JNYW5hZ2VyKCkuam9pbigib3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5mYW1pbHkiLCBuZXcgTnVsbFByb2dyZXNzTW9uaXRvcigpKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5XQVJOSU5HLCAiRXJyb3Igd2FpdGluZyBmb3Igam9iIiwgZSk7CgkJfQoJCQoJCXJldHVybiBzZXJ2ZXI7Cgl9CgoJLyoqCgkgKiBSdW4gdGhlIHJlc291cmNlIG9uIGEgc2VydmVyLgoJICovCglwcm90ZWN0ZWQgdm9pZCBydW4oKSB7CgkJZmluYWwgSU1vZHVsZUFydGlmYWN0W10gbW9kdWxlQXJ0aWZhY3RzID0gU2VydmVyUGx1Z2luLmdldE1vZHVsZUFydGlmYWN0cyhzZWxlY3Rpb24pOwoJCWlmIChtb2R1bGVBcnRpZmFjdHMgPT0gbnVsbCB8fCBtb2R1bGVBcnRpZmFjdHMubGVuZ3RoID09IDAgfHwgbW9kdWxlQXJ0aWZhY3RzWzBdID09IG51bGwpIHsKCQkJRWNsaXBzZVV0aWwub3BlbkVycm9yKE1lc3NhZ2VzLmVycm9yTm9BcnRpZmFjdCk7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIk5vIG1vZHVsZSBhcnRpZmFjdCBmb3VuZCIpOwoJCQlyZXR1cm47CgkJfQoJCQoJCVNoZWxsIHNoZWxsMiA9IG51bGw7CgkJaWYgKHdpbmRvdyAhPSBudWxsKQoJCQlzaGVsbDIgPSB3aW5kb3cuZ2V0U2hlbGwoKTsKCQllbHNlIHsKCQkJdHJ5IHsKCQkJCXNoZWxsMiA9IFNlcnZlclVJUGx1Z2luLmdldEluc3RhbmNlKCkuZ2V0V29ya2JlbmNoKCkuZ2V0QWN0aXZlV29ya2JlbmNoV2luZG93KCkuZ2V0U2hlbGwoKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCS8vIGlnbm9yZQoJCQl9CgkJCWlmIChzaGVsbDIgPT0gbnVsbCkKCQkJCXNoZWxsMiA9IERpc3BsYXkuZ2V0RGVmYXVsdCgpLmdldEFjdGl2ZVNoZWxsKCk7CgkJfQoJCWZpbmFsIFNoZWxsIHNoZWxsID0gc2hlbGwyOwoJCQoJCS8vIGdldCBhIHZhbGlkIE1vZHVsZUFydGlmYWN0IHRoYXQgd2UgY2FuIHVzZSBmb3IgbGF1bmNoaW5nCgkJLy8gVE9ETyBUaGUgTW9kdWxlQXJ0aWZhY3RDb21wb3NpdGUgc2hvdWxkIGJlIHBhcnQgb2YgdGhlIFJ1bk9uU2VydmVyV2l6YXJkCgkJZmluYWwgSU1vZHVsZUFydGlmYWN0IG1vZHVsZUFydGlmYWN0OwoJCWlmIChtb2R1bGVBcnRpZmFjdHMubGVuZ3RoID4gMSkgewoJCQlNb2R1bGVBcnRpZmFjdENvbXBvc2l0ZSBhcnRpZmFjdENvbXBvc2l0ZSA9IG5ldyBNb2R1bGVBcnRpZmFjdENvbXBvc2l0ZShzaGVsbCwgbW9kdWxlQXJ0aWZhY3RzLCBsYXVuY2hNb2RlKTsKCQkJaWYgKGFydGlmYWN0Q29tcG9zaXRlLm9wZW4oKSA9PSBXaW5kb3cuQ0FOQ0VMKQoJCQkJcmV0dXJuOwoJCQkKCQkJbW9kdWxlQXJ0aWZhY3QgPSBhcnRpZmFjdENvbXBvc2l0ZS5nZXRTZWxlY3Rpb24oKTsKCQl9IGVsc2UKCQkJbW9kdWxlQXJ0aWZhY3QgPSBtb2R1bGVBcnRpZmFjdHNbMF07CgkJCgkJaWYgKG1vZHVsZUFydGlmYWN0LmdldE1vZHVsZSgpID09IG51bGwpIHsgLy8gMTQ5NDI1CgkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihNZXNzYWdlcy5lcnJvck5vTW9kdWxlcyk7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIk1vZHVsZSBhcnRpZmFjdCBub3QgY29udGFpbmVkIGluIGEgbW9kdWxlIik7CgkJCXJldHVybjsKCQl9CgkJZmluYWwgSU1vZHVsZSBtb2R1bGUgPSBtb2R1bGVBcnRpZmFjdC5nZXRNb2R1bGUoKTsKCQkKCQkvLyBjaGVjayBmb3Igc2VydmVycyB3aXRoIHRoZSBnaXZlbiBzdGFydCBtb2RlCgkJSVNlcnZlcltdIHNlcnZlcnMgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlcnMoKTsKCQlib29sZWFuIGZvdW5kID0gZmFsc2U7CgkJaWYgKHNlcnZlcnMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IHNlcnZlcnMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemUgJiYgIWZvdW5kOyBpKyspIHsKCQkJCWlmIChTZXJ2ZXJVSVBsdWdpbi5pc0NvbXBhdGlibGVXaXRoTGF1bmNoTW9kZShzZXJ2ZXJzW2ldLCBsYXVuY2hNb2RlKSkgewoJCQkJCXRyeSB7CgkJCQkJCUlNb2R1bGVbXSBwYXJlbnRzID0gc2VydmVyc1tpXS5nZXRSb290TW9kdWxlcyhtb2R1bGUsIG51bGwpOwoJCQkJCQlpZiAocGFyZW50cyAhPSBudWxsICYmIHBhcmVudHMubGVuZ3RoID4gMCkKCQkJCQkJCWZvdW5kID0gdHJ1ZTsKCQkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCQkvLyBpZ25vcmUKCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkJCgkJaWYgKCFmb3VuZCkgewoJCQkvLyBubyBleGlzdGluZyBzZXJ2ZXIgc3VwcG9ydHMgdGhlIHByb2plY3QgYW5kIHN0YXJ0IG1vZGUhCgkJCS8vIGNoZWNrIGlmIHRoZXJlIG1pZ2h0IGJlIGFub3RoZXIgb25lIHRoYXQgY2FuIGJlIGNyZWF0ZWQKCQkJSVNlcnZlclR5cGVbXSBzZXJ2ZXJUeXBlcyA9IFNlcnZlckNvcmUuZ2V0U2VydmVyVHlwZXMoKTsKCQkJaWYgKHNlcnZlclR5cGVzICE9IG51bGwpIHsKCQkJCWludCBzaXplID0gc2VydmVyVHlwZXMubGVuZ3RoOwoJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplICYmICFmb3VuZDsgaSsrKSB7CgkJCQkJSVNlcnZlclR5cGUgdHlwZSA9IHNlcnZlclR5cGVzW2ldOwoJCQkJCUlNb2R1bGVUeXBlW10gbW9kdWxlVHlwZXMgPSB0eXBlLmdldFJ1bnRpbWVUeXBlKCkuZ2V0TW9kdWxlVHlwZXMoKTsKCQkJCQlpZiAodHlwZS5zdXBwb3J0c0xhdW5jaE1vZGUobGF1bmNoTW9kZSkgJiYgU2VydmVyVXRpbC5pc1N1cHBvcnRlZE1vZHVsZShtb2R1bGVUeXBlcywgbW9kdWxlLmdldE1vZHVsZVR5cGUoKSkpIHsKCQkJCQkJZm91bmQgPSB0cnVlOwoJCQkJCX0KCQkJCX0KCQkJfQoJCQlpZiAoIWZvdW5kKSB7CgkJCQlFY2xpcHNlVXRpbC5vcGVuRXJyb3IoTWVzc2FnZXMuZXJyb3JOb1NlcnZlcik7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJObyBzZXJ2ZXIgZm9yIHN0YXJ0IG1vZGUiKTsKCQkJCXJldHVybjsKCQkJfQoJCX0KCQkKCQlpZiAoIVNlcnZlclVJUGx1Z2luLnNhdmVFZGl0b3JzKCkpCgkJCXJldHVybjsKCQkKCQl0YXNrc0FuZENsaWVudFNob3duID0gZmFsc2U7CgkJSVNlcnZlciBzZXJ2ZXIyID0gbnVsbDsKCQljbGllbnQgPSBudWxsOwoJCWxhdW5jaGFibGVBZGFwdGVyID0gbnVsbDsKCQl0cnkgewoJCQlJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IgPSBuZXcgTnVsbFByb2dyZXNzTW9uaXRvcigpOwoJCQlzZXJ2ZXIyID0gZ2V0U2VydmVyKG1vZHVsZSwgbW9kdWxlQXJ0aWZhY3QsIG1vbml0b3IpOwoJCQlpZiAobW9uaXRvci5pc0NhbmNlbGVkKCkpCgkJCQlyZXR1cm47CgkJCQoJCQlpZiAoc2VydmVyMiAhPSBudWxsKSB7CgkJCQlJRm9sZGVyIGZvbGRlciA9IHNlcnZlcjIuZ2V0U2VydmVyQ29uZmlndXJhdGlvbigpOwoJCQkJaWYgKGZvbGRlciAhPSBudWxsICYmIGZvbGRlci5nZXRQcm9qZWN0KCkgIT0gbnVsbCAmJiAhZm9sZGVyLmdldFByb2plY3QoKS5pc09wZW4oKSkKCQkJCQlmb2xkZXIuZ2V0UHJvamVjdCgpLm9wZW4obW9uaXRvcik7CgkJCX0KCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihzaGVsbCwgY2UuZ2V0TG9jYWxpemVkTWVzc2FnZSgpKTsKCQkJcmV0dXJuOwoJCX0KCQlmaW5hbCBJU2VydmVyIHNlcnZlciA9IHNlcnZlcjI7CgkJLy9pZiAobW9uaXRvci5pc0NhbmNlbGVkKCkpCgkJLy8JcmV0dXJuOwoJCQoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlNlcnZlcjogIiArIHNlcnZlcik7CgkJCgkJaWYgKHNlcnZlciA9PSBudWxsKSB7CgkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihNZXNzYWdlcy5lcnJvck5vU2VydmVyKTsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiTm8gc2VydmVyIGZvdW5kIik7CgkJCXJldHVybjsKCQl9CgkJCgkJaWYgKCFTZXJ2ZXJVSVBsdWdpbi5wcm9tcHRJZkRpcnR5KHNoZWxsLCBzZXJ2ZXIpKQoJCQlyZXR1cm47CgkJCgkJaWYgKCF0YXNrc0FuZENsaWVudFNob3duKSB7CgkJCVJ1bk9uU2VydmVyV2l6YXJkIHdpemFyZCA9IG5ldyBSdW5PblNlcnZlcldpemFyZChzZXJ2ZXIsIGxhdW5jaE1vZGUsIG1vZHVsZUFydGlmYWN0KTsKCQkJaWYgKHdpemFyZC5zaG91bGRBcHBlYXIoKSkgewoJCQkJV2l6YXJkRGlhbG9nIGRpYWxvZyA9IG5ldyBXaXphcmREaWFsb2coc2hlbGwsIHdpemFyZCk7CgkJCQlpZiAoZGlhbG9nLm9wZW4oKSA9PSBXaW5kb3cuQ0FOQ0VMKQoJCQkJCXJldHVybjsKCQkJfSBlbHNlCgkJCQl3aXphcmQucGVyZm9ybUZpbmlzaCgpOwoJCQljbGllbnQgPSB3aXphcmQuZ2V0U2VsZWN0ZWRDbGllbnQoKTsKCQkJbGF1bmNoYWJsZUFkYXB0ZXIgPSB3aXphcmQuZ2V0TGF1bmNoYWJsZUFkYXB0ZXIoKTsKCQl9CgkJCQoJCS8vIGlmIHRoZXJlIGlzIG5vIGNsaWVudCwgdXNlIGEgZHVtbXkKCQlpZiAoY2xpZW50ID09IG51bGwpewkJCgkJCQljbGllbnQgPSBuZXcgSUNsaWVudCgpIHsKCQkJCQlwdWJsaWMgU3RyaW5nIGdldERlc2NyaXB0aW9uKCkgewoJCQkJCQlyZXR1cm4gTWVzc2FnZXMuY2xpZW50RGVmYXVsdERlc2NyaXB0aW9uOwoJCQkJCX0KCgkJCQkJcHVibGljIFN0cmluZyBnZXRJZCgpIHsKCQkJCQkJcmV0dXJuICJvcmcuZWNsaXBzZS53c3RoLnNlcnZlci51aS5jbGllbnQuZGVmYXVsdCI7CgkJCQkJfQoKCQkJCQlwdWJsaWMgU3RyaW5nIGdldE5hbWUoKSB7CgkJCQkJCXJldHVybiBNZXNzYWdlcy5jbGllbnREZWZhdWx0TmFtZTsKCQkJCQl9CgoJCQkJCXB1YmxpYyBJU3RhdHVzIGxhdW5jaChJU2VydmVyIHNlcnZlcjMsIE9iamVjdCBsYXVuY2hhYmxlMiwgU3RyaW5nIGxhdW5jaE1vZGUzLCBJTGF1bmNoIGxhdW5jaCkgewoJCQkJCQlyZXR1cm4gU3RhdHVzLk9LX1NUQVRVUzsKCQkJCQl9CgoJCQkJCXB1YmxpYyBib29sZWFuIHN1cHBvcnRzKElTZXJ2ZXIgc2VydmVyMywgT2JqZWN0IGxhdW5jaGFibGUyLCBTdHJpbmcgbGF1bmNoTW9kZTMpIHsKCQkJCQkJcmV0dXJuIHRydWU7CgkJCQkJfQoJCQkJfTsKCQl9CQkKCQkKCQlpZiAobW9kdWxlQXJ0aWZhY3QgaW5zdGFuY2VvZiBNb2R1bGVBcnRpZmFjdERlbGVnYXRlKSB7CgkJCWJvb2xlYW4gY2FuTG9hZCA9IGZhbHNlOwoJCQl0cnkgewoJCQkJQ2xhc3MgYyA9IENsYXNzLmZvck5hbWUobW9kdWxlQXJ0aWZhY3QuZ2V0Q2xhc3MoKS5nZXROYW1lKCkpOwoJCQkJaWYgKGMubmV3SW5zdGFuY2UoKSAhPSBudWxsKQoJCQkJCWNhbkxvYWQgPSB0cnVlOwoJCQl9IGNhdGNoIChUaHJvd2FibGUgdCkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuV0FSTklORywgIkNvdWxkIG5vdCBsb2FkIG1vZHVsZSBhcnRpZmFjdCBkZWxlZ2F0ZSBjbGFzcywgc3dpdGNoaW5nIHRvIGJhY2t1cCIpOwoJCQl9CgkJCWlmIChjYW5Mb2FkKSB7CgkJCQl0cnkgewoJCQkJCUlQcm9ncmVzc01vbml0b3IgbW9uaXRvciA9IG5ldyBOdWxsUHJvZ3Jlc3NNb25pdG9yKCk7CgkJCQkJSUxhdW5jaENvbmZpZ3VyYXRpb24gY29uZmlnID0gZ2V0TGF1bmNoQ29uZmlndXJhdGlvbihzZXJ2ZXIsIChNb2R1bGVBcnRpZmFjdERlbGVnYXRlKSBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIsIGNsaWVudCwgbW9uaXRvcik7CgkJCQkJY29uZmlnLmxhdW5jaChsYXVuY2hNb2RlLCBtb25pdG9yKTsKCQkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJDb3VsZCBub3QgbGF1bmNoIFJ1biBvbiBTZXJ2ZXIiLCBjZSk7CgkJCQl9CgkJCQlyZXR1cm47CgkJCX0KCQl9CgkJCgkJVGhyZWFkIHRocmVhZCA9IG5ldyBUaHJlYWQoIlJ1biBvbiBTZXJ2ZXIiKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlJlYWR5IHRvIGxhdW5jaCIpOwoJCQkJCgkJCQkvLyBzdGFydCBzZXJ2ZXIgaWYgaXQncyBub3QgYWxyZWFkeSBzdGFydGVkCgkJCQkvLyBhbmQgY3VlIHRoZSBjbGllbnQgdG8gc3RhcnQKCQkJCUlNb2R1bGVbXSBtb2R1bGVzID0gbmV3IElNb2R1bGVbXSB7IG1vZHVsZSB9OyAvLyBUT0RPOiBnZXQgcGFyZW50IGhpZXJhcmNoeSBjb3JyZWN0CgkJCQlpbnQgc3RhdGUgPSBzZXJ2ZXIuZ2V0U2VydmVyU3RhdGUoKTsKCQkJCWlmIChzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUQVJUSU5HKSB7CgkJCQkJTGF1bmNoQ2xpZW50Sm9iIGNsaWVudEpvYiA9IG5ldyBMYXVuY2hDbGllbnRKb2Ioc2VydmVyLCBtb2R1bGVzLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIsIGNsaWVudCk7CgkJCQkJY2xpZW50Sm9iLnNjaGVkdWxlKCk7CgkJCQl9IGVsc2UgaWYgKHN0YXRlID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCkgewoJCQkJCWJvb2xlYW4gcmVzdGFydCA9IGZhbHNlOwoJCQkJCVN0cmluZyBtb2RlID0gc2VydmVyLmdldE1vZGUoKTsKCQkJCQlJQnJlYWtwb2ludE1hbmFnZXIgYnJlYWtwb2ludE1hbmFnZXIgPSBEZWJ1Z1BsdWdpbi5nZXREZWZhdWx0KCkuZ2V0QnJlYWtwb2ludE1hbmFnZXIoKTsKCQkJCQlib29sZWFuIGRpc2FibGVkQnJlYWtwb2ludHMgPSBmYWxzZTsKCQkJCQkKCQkJCQlpZiAoc2VydmVyLmdldFNlcnZlclJlc3RhcnRTdGF0ZSgpKSB7CgkJCQkJCWludCByZXN1bHQgPSBvcGVuUmVzdGFydERpYWxvZyhzaGVsbCk7CgkJCQkJCWlmIChyZXN1bHQgPT0gMCkgewoJCQkJCQkJbGF1bmNoTW9kZSA9IG1vZGU7CgkJCQkJCQlyZXN0YXJ0ID0gdHJ1ZTsKCQkJCQkJfSBlbHNlIGlmIChyZXN1bHQgPT0gOSkgLy8gY2FuY2VsCgkJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJCWlmICghcmVzdGFydCkgewoJCQkJCQlpZiAoIUlMYXVuY2hNYW5hZ2VyLlJVTl9NT0RFLmVxdWFscyhtb2RlKSAmJiBJTGF1bmNoTWFuYWdlci5SVU5fTU9ERS5lcXVhbHMobGF1bmNoTW9kZSkpIHsKCQkJCQkJCWJvb2xlYW4gYnJlYWtwb2ludHNPcHRpb24gPSBmYWxzZTsKCQkJCQkJCWlmIChicmVha3BvaW50TWFuYWdlci5pc0VuYWJsZWQoKSAmJiBJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLmVxdWFscyhtb2RlKSkKCQkJCQkJCQlicmVha3BvaW50c09wdGlvbiA9IHRydWU7CgkJCQkJCQlpbnQgcmVzdWx0ID0gb3Blbk9wdGlvbnNEaWFsb2coc2hlbGwsIE1lc3NhZ2VzLndpelJ1bk9uU2VydmVyVGl0bGUsIE1lc3NhZ2VzLmRpYWxvZ01vZGVXYXJuaW5nUnVuLCBicmVha3BvaW50c09wdGlvbik7CgkJCQkJCQlpZiAocmVzdWx0ID09IDApCgkJCQkJCQkJcmVzdGFydCA9IHRydWU7CgkJCQkJCQllbHNlIGlmIChyZXN1bHQgPT0gMSkgewoJCQkJCQkJCWJyZWFrcG9pbnRNYW5hZ2VyLnNldEVuYWJsZWQoZmFsc2UpOwoJCQkJCQkJCWRpc2FibGVkQnJlYWtwb2ludHMgPSB0cnVlOwoJCQkJCQkJCWxhdW5jaE1vZGUgPSBtb2RlOwoJCQkJCQkJfSBlbHNlIGlmIChyZXN1bHQgPT0gMikKCQkJCQkJCQlsYXVuY2hNb2RlID0gbW9kZTsKCQkJCQkJCWVsc2UgLy8gcmVzdWx0ID09IDkgLy8gY2FuY2VsCgkJCQkJCQkJcmV0dXJuOwoJCQkJCQl9IGVsc2UgaWYgKCFJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLmVxdWFscyhtb2RlKSAmJiBJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLmVxdWFscyhsYXVuY2hNb2RlKSkgewoJCQkJCQkJaW50IHJlc3VsdCA9IG9wZW5PcHRpb25zRGlhbG9nKHNoZWxsLCBNZXNzYWdlcy53aXpEZWJ1Z09uU2VydmVyVGl0bGUsIE1lc3NhZ2VzLmRpYWxvZ01vZGVXYXJuaW5nRGVidWcsIGZhbHNlKTsKCQkJCQkJCWlmIChyZXN1bHQgPT0gMCkKCQkJCQkJCQlyZXN0YXJ0ID0gdHJ1ZTsKCQkJCQkJCWVsc2UgaWYgKHJlc3VsdCA9PSAxKQoJCQkJCQkJCWxhdW5jaE1vZGUgPSBtb2RlOwoJCQkJCQkJZWxzZSAvLyByZXN1bHQgPT0gOSAvLyBjYW5jZWwKCQkJCQkJCQlyZXR1cm47CgkJCQkJCX0gZWxzZSBpZiAoIUlMYXVuY2hNYW5hZ2VyLlBST0ZJTEVfTU9ERS5lcXVhbHMobW9kZSkgJiYgSUxhdW5jaE1hbmFnZXIuUFJPRklMRV9NT0RFLmVxdWFscyhsYXVuY2hNb2RlKSkgewoJCQkJCQkJYm9vbGVhbiBicmVha3BvaW50c09wdGlvbiA9IGZhbHNlOwoJCQkJCQkJaWYgKGJyZWFrcG9pbnRNYW5hZ2VyLmlzRW5hYmxlZCgpICYmIElMYXVuY2hNYW5hZ2VyLkRFQlVHX01PREUuZXF1YWxzKG1vZGUpKQoJCQkJCQkJCWJyZWFrcG9pbnRzT3B0aW9uID0gdHJ1ZTsKCQkJCQkJCWludCByZXN1bHQgPSBvcGVuT3B0aW9uc0RpYWxvZyhzaGVsbCwgTWVzc2FnZXMud2l6UHJvZmlsZU9uU2VydmVyVGl0bGUsIE1lc3NhZ2VzLmRpYWxvZ01vZGVXYXJuaW5nUHJvZmlsZSwgYnJlYWtwb2ludHNPcHRpb24pOwoJCQkJCQkJaWYgKHJlc3VsdCA9PSAwKQoJCQkJCQkJCXJlc3RhcnQgPSB0cnVlOwoJCQkJCQkJZWxzZSBpZiAocmVzdWx0ID09IDEpIHsKCQkJCQkJCQlicmVha3BvaW50TWFuYWdlci5zZXRFbmFibGVkKGZhbHNlKTsKCQkJCQkJCQlkaXNhYmxlZEJyZWFrcG9pbnRzID0gdHJ1ZTsKCQkJCQkJCQlsYXVuY2hNb2RlID0gbW9kZTsKCQkJCQkJCX0gZWxzZSBpZiAocmVzdWx0ID09IDIpCgkJCQkJCQkJbGF1bmNoTW9kZSA9IG1vZGU7CgkJCQkJCQllbHNlIC8vIHJlc3VsdCA9PSA5IC8vIGNhbmNlbAoJCQkJCQkJCXJldHVybjsKCQkJCQkJfQoJCQkJCQkKCQkJCQkJaWYgKElMYXVuY2hNYW5hZ2VyLkRFQlVHX01PREUuZXF1YWxzKGxhdW5jaE1vZGUpKSB7CgkJCQkJCQlpZiAoIWJyZWFrcG9pbnRNYW5hZ2VyLmlzRW5hYmxlZCgpICYmICFkaXNhYmxlZEJyZWFrcG9pbnRzKSB7CgkJCQkJCQkJaW50IHJlc3VsdCA9IG9wZW5CcmVha3BvaW50RGlhbG9nKHNoZWxsKTsKCQkJCQkJCQlpZiAocmVzdWx0ID09IDApCgkJCQkJCQkJCWJyZWFrcG9pbnRNYW5hZ2VyLnNldEVuYWJsZWQodHJ1ZSk7CgkJCQkJCQkJZWxzZSBpZiAocmVzdWx0ID09IDEpIHsKCQkJCQkJCQkJLy8gaWdub3JlCgkJCQkJCQkJfSBlbHNlIC8vIHJlc3VsdCA9PSAyCgkJCQkJCQkJCXJldHVybjsKCQkJCQkJCX0KCQkJCQkJfQoJCQkJCX0KCQkJCQkKCQkJCQlQdWJsaXNoU2VydmVySm9iIHB1Ymxpc2hKb2IgPSBuZXcgUHVibGlzaFNlcnZlckpvYihzZXJ2ZXIsIElTZXJ2ZXIuUFVCTElTSF9JTkNSRU1FTlRBTCwgZmFsc2UpOwoJCQkJCUxhdW5jaENsaWVudEpvYiBjbGllbnRKb2IgPSBuZXcgTGF1bmNoQ2xpZW50Sm9iKHNlcnZlciwgbW9kdWxlcywgbGF1bmNoTW9kZSwgbW9kdWxlQXJ0aWZhY3QsIGxhdW5jaGFibGVBZGFwdGVyLCBjbGllbnQpOwoJCQkJCXB1Ymxpc2hKb2Iuc2V0TmV4dEpvYihjbGllbnRKb2IpOwoJCQkJCQoJCQkJCWlmIChyZXN0YXJ0KSB7CgkJCQkJCVJlc3RhcnRTZXJ2ZXJKb2IgcmVzdGFydEpvYiA9IG5ldyBSZXN0YXJ0U2VydmVySm9iKHNlcnZlciwgbGF1bmNoTW9kZSk7CgkJCQkJCXJlc3RhcnRKb2Iuc2V0TmV4dEpvYihwdWJsaXNoSm9iKTsKCQkJCQkJcmVzdGFydEpvYi5zY2hlZHVsZSgpOwoJCQkJCX0gZWxzZQoJCQkJCQlwdWJsaXNoSm9iLnNjaGVkdWxlKCk7CgkJCQl9IGVsc2UgaWYgKHN0YXRlICE9IElTZXJ2ZXIuU1RBVEVfU1RPUFBJTkcpIHsKCQkJCQlQdWJsaXNoU2VydmVySm9iIHB1Ymxpc2hKb2IgPSBuZXcgUHVibGlzaFNlcnZlckpvYihzZXJ2ZXIpOwoJCQkJCVN0YXJ0U2VydmVySm9iIHN0YXJ0U2VydmVySm9iID0gbmV3IFN0YXJ0U2VydmVySm9iKHNlcnZlciwgbGF1bmNoTW9kZSk7CgkJCQkJTGF1bmNoQ2xpZW50Sm9iIGNsaWVudEpvYiA9IG5ldyBMYXVuY2hDbGllbnRKb2Ioc2VydmVyLCBtb2R1bGVzLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIsIGNsaWVudCk7CgkJCQkJCgkJCQkJaWYgKCgoU2VydmVyVHlwZSlzZXJ2ZXIuZ2V0U2VydmVyVHlwZSgpKS5zdGFydEJlZm9yZVB1Ymxpc2goKSkgewoJCQkJCQlzdGFydFNlcnZlckpvYi5zZXROZXh0Sm9iKHB1Ymxpc2hKb2IpOwoJCQkJCQlwdWJsaXNoSm9iLnNldE5leHRKb2IoY2xpZW50Sm9iKTsKCQkJCQkJc3RhcnRTZXJ2ZXJKb2Iuc2NoZWR1bGUoKTsKCQkJCQl9IGVsc2UgewoJCQkJCQlwdWJsaXNoSm9iLnNldE5leHRKb2Ioc3RhcnRTZXJ2ZXJKb2IpOwoJCQkJCQlzdGFydFNlcnZlckpvYi5zZXROZXh0Sm9iKGNsaWVudEpvYik7CgkJCQkJCXB1Ymxpc2hKb2Iuc2NoZWR1bGUoKTsKCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCXRocmVhZC5zZXREYWVtb24odHJ1ZSk7CgkJdGhyZWFkLnN0YXJ0KCk7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKElMYXVuY2hDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgY29uZmlnLCBJU2VydmVyIHNlcnZlciwgTW9kdWxlQXJ0aWZhY3REZWxlZ2F0ZSBtb2R1bGVBcnRpZmFjdCwgSUxhdW5jaGFibGVBZGFwdGVyIGxhdW5jaGFibGVBZGFwdGVyLCBJQ2xpZW50IGNsaWVudCkgewoJCWNvbmZpZy5zZXRBdHRyaWJ1dGUoUnVuT25TZXJ2ZXJMYXVuY2hDb25maWd1cmF0aW9uRGVsZWdhdGUuQVRUUl9TRVJWRVJfSUQsIHNlcnZlci5nZXRJZCgpKTsKCQljb25maWcuc2V0QXR0cmlidXRlKFJ1bk9uU2VydmVyTGF1bmNoQ29uZmlndXJhdGlvbkRlbGVnYXRlLkFUVFJfTU9EVUxFX0FSVElGQUNULCBtb2R1bGVBcnRpZmFjdC5zZXJpYWxpemUoKSk7CgkJY29uZmlnLnNldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX01PRFVMRV9BUlRJRkFDVF9DTEFTUywgbW9kdWxlQXJ0aWZhY3QuZ2V0Q2xhc3MoKS5nZXROYW1lKCkpOwoJCWNvbmZpZy5zZXRBdHRyaWJ1dGUoUnVuT25TZXJ2ZXJMYXVuY2hDb25maWd1cmF0aW9uRGVsZWdhdGUuQVRUUl9MQVVOQ0hBQkxFX0FEQVBURVJfSUQsIGxhdW5jaGFibGVBZGFwdGVyLmdldElkKCkpOwoJCWNvbmZpZy5zZXRBdHRyaWJ1dGUoUnVuT25TZXJ2ZXJMYXVuY2hDb25maWd1cmF0aW9uRGVsZWdhdGUuQVRUUl9DTElFTlRfSUQsIGNsaWVudC5nZXRJZCgpKTsKCX0KCglwcm90ZWN0ZWQgSUxhdW5jaENvbmZpZ3VyYXRpb24gZ2V0TGF1bmNoQ29uZmlndXJhdGlvbihJU2VydmVyIHNlcnZlciwgTW9kdWxlQXJ0aWZhY3REZWxlZ2F0ZSBtb2R1bGVBcnRpZmFjdCwgSUxhdW5jaGFibGVBZGFwdGVyIGxhdW5jaGFibGVBZGFwdGVyMiwgSUNsaWVudCBjbGllbnQyLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCQlTdHJpbmcgc2VydmVySWQgPSBzZXJ2ZXIuZ2V0SWQoKTsKCQlJTGF1bmNoTWFuYWdlciBsYXVuY2hNYW5hZ2VyID0gRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldExhdW5jaE1hbmFnZXIoKTsKCQlJTGF1bmNoQ29uZmlndXJhdGlvblR5cGUgbGF1bmNoQ29uZmlnVHlwZSA9IGxhdW5jaE1hbmFnZXIuZ2V0TGF1bmNoQ29uZmlndXJhdGlvblR5cGUoIm9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkubGF1bmNoQ29uZmlndXJhdGlvblR5cGUiKTsKCQlJTGF1bmNoQ29uZmlndXJhdGlvbltdIGxhdW5jaENvbmZpZ3MgPSBudWxsOwoJCXRyeSB7CgkJCWxhdW5jaENvbmZpZ3MgPSBsYXVuY2hNYW5hZ2VyLmdldExhdW5jaENvbmZpZ3VyYXRpb25zKGxhdW5jaENvbmZpZ1R5cGUpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJCgkJaWYgKGxhdW5jaENvbmZpZ3MgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IGxhdW5jaENvbmZpZ3MubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJTGlzdCBsaXN0ID0gbGF1bmNoQ29uZmlnc1tpXS5nZXRBdHRyaWJ1dGUoSURlYnVnVUlDb25zdGFudHMuQVRUUl9GQVZPUklURV9HUk9VUFMsIChMaXN0KW51bGwpOwoJCQkJaWYgKGxpc3QgPT0gbnVsbCB8fCBsaXN0LmlzRW1wdHkoKSkgewoJCQkJCXRyeSB7CgkJCQkJCVN0cmluZyBzZXJ2ZXJJZDIgPSBsYXVuY2hDb25maWdzW2ldLmdldEF0dHJpYnV0ZShSdW5PblNlcnZlckxhdW5jaENvbmZpZ3VyYXRpb25EZWxlZ2F0ZS5BVFRSX1NFUlZFUl9JRCwgKFN0cmluZykgbnVsbCk7CgkJCQkJCWlmIChzZXJ2ZXJJZC5lcXVhbHMoc2VydmVySWQyKSkgewoJCQkJCQkJZmluYWwgSUxhdW5jaENvbmZpZ3VyYXRpb25Xb3JraW5nQ29weSB3YyA9IGxhdW5jaENvbmZpZ3NbaV0uZ2V0V29ya2luZ0NvcHkoKTsKCQkJCQkJCXNldHVwTGF1bmNoQ29uZmlndXJhdGlvbih3Yywgc2VydmVyLCBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIyLCBjbGllbnQyKTsKCQkJCQkJCWlmICh3Yy5pc0RpcnR5KCkpIHsKCQkJCQkJCQl0cnkgewoJCQkJCQkJCQlyZXR1cm4gd2MuZG9TYXZlKCk7CgkJCQkJCQkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjb25maWd1cmluZyBsYXVuY2giLCBjZSk7CgkJCQkJCQkJfQoJCQkJCQkJfQoJCQkJCQkJcmV0dXJuIGxhdW5jaENvbmZpZ3NbaV07CgkJCQkJCX0KCQkJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGUpIHsKCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY29uZmlndXJpbmcgbGF1bmNoIiwgZSk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCQoJCS8vIGNyZWF0ZSBhIG5ldyBsYXVuY2ggY29uZmlndXJhdGlvbgoJCVN0cmluZyBsYXVuY2hOYW1lID0gTkxTLmJpbmQoTWVzc2FnZXMucnVuT25TZXJ2ZXJMYXVuY2hDb25maWdOYW1lLCBtb2R1bGVBcnRpZmFjdC5nZXROYW1lKCkpOwoJCWxhdW5jaE5hbWUgPSBnZXRWYWxpZExhdW5jaENvbmZpZ3VyYXRpb25OYW1lKGxhdW5jaE5hbWUpOwoJCWxhdW5jaE5hbWUgPSBsYXVuY2hNYW5hZ2VyLmdlbmVyYXRlVW5pcXVlTGF1bmNoQ29uZmlndXJhdGlvbk5hbWVGcm9tKGxhdW5jaE5hbWUpOyAKCQlJTGF1bmNoQ29uZmlndXJhdGlvbldvcmtpbmdDb3B5IHdjID0gbGF1bmNoQ29uZmlnVHlwZS5uZXdJbnN0YW5jZShudWxsLCBsYXVuY2hOYW1lKTsKCQl3Yy5zZXRBdHRyaWJ1dGUoUnVuT25TZXJ2ZXJMYXVuY2hDb25maWd1cmF0aW9uRGVsZWdhdGUuQVRUUl9TRVJWRVJfSUQsIHNlcnZlcklkKTsKCQlzZXR1cExhdW5jaENvbmZpZ3VyYXRpb24od2MsIHNlcnZlciwgbW9kdWxlQXJ0aWZhY3QsIGxhdW5jaGFibGVBZGFwdGVyMiwgY2xpZW50Mik7CgkJcmV0dXJuIHdjLmRvU2F2ZSgpOwoJfQoKCS8vcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBjaGFyW10gSU5WQUxJRF9DSEFSUyA9IG5ldyBjaGFyW10geydcXCcsICcvJywgJzonLCAnKicsICc/JywgJyInLCAnPCcsICc+JywgJ3wnLCAnXDAnLCAnQCcsICcmJ307Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIGNoYXJbXSBJTlZBTElEX0NIQVJTID0gbmV3IGNoYXJbXSB7J1xcJywgJzonLCAnKicsICc/JywgJyInLCAnPCcsICc+JywgJ3wnLCAnXDAnLCAnQCcsICcmJ307Cglwcm90ZWN0ZWQgU3RyaW5nIGdldFZhbGlkTGF1bmNoQ29uZmlndXJhdGlvbk5hbWUoU3RyaW5nIHMpIHsKCQlpZiAocyA9PSBudWxsIHx8IHMubGVuZ3RoKCkgPT0gMCkKCQkJcmV0dXJuICIxIjsKCQlpbnQgc2l6ZSA9IElOVkFMSURfQ0hBUlMubGVuZ3RoOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCXMgPSBzLnJlcGxhY2UoSU5WQUxJRF9DSEFSU1tpXSwgJ18nKTsKCQl9CgkJcmV0dXJuIHM7Cgl9CgoJLyoqCgkgKiBPcGVuIGFuIG9wdGlvbnMgZGlhbG9nLgoJICogCgkgKiBAcGFyYW0gc2hlbGwKCSAqIEBwYXJhbSB0aXRsZQoJICogQHBhcmFtIG1lc3NhZ2UKCSAqIEBwYXJhbSBicmVha3BvaW50c09wdGlvbgoJICogQHJldHVybiBhIGRpYWxvZyByZXR1cm4gY29uc3RhbnQKCSAqLwoJcHJvdGVjdGVkIHN0YXRpYyBpbnQgb3Blbk9wdGlvbnNEaWFsb2coZmluYWwgU2hlbGwgc2hlbGwsIGZpbmFsIFN0cmluZyB0aXRsZSwgZmluYWwgU3RyaW5nIG1lc3NhZ2UsIGZpbmFsIGJvb2xlYW4gYnJlYWtwb2ludHNPcHRpb24pIHsKCQlpZiAoYnJlYWtwb2ludHNPcHRpb24pIHsKCQkJaW50IGN1cnJlbnQgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLmdldExhdW5jaE1vZGUyKCk7CgkJCWlmIChjdXJyZW50ID09IFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREUyX1JFU1RBUlQpCgkJCQlyZXR1cm4gMDsKCQkJZWxzZSBpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLkxBVU5DSF9NT0RFMl9ESVNBQkxFX0JSRUFLUE9JTlRTKQoJCQkJcmV0dXJuIDE7CgkJCWVsc2UgaWYgKGN1cnJlbnQgPT0gU2VydmVyVUlQcmVmZXJlbmNlcy5MQVVOQ0hfTU9ERTJfQ09OVElOVUUpCgkJCQlyZXR1cm4gMjsKCQl9IGVsc2UgewoJCQlpbnQgY3VycmVudCA9IFNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuZ2V0TGF1bmNoTW9kZSgpOwoJCQlpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLkxBVU5DSF9NT0RFX1JFU1RBUlQpCgkJCQlyZXR1cm4gMDsKCQkJZWxzZSBpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLkxBVU5DSF9NT0RFX0NPTlRJTlVFKQoJCQkJcmV0dXJuIDE7CgkJfQoJCWZpbmFsIGludFtdIGkgPSBuZXcgaW50WzFdOwoJCXNoZWxsLmdldERpc3BsYXkoKS5zeW5jRXhlYyhuZXcgUnVubmFibGUoKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCU9wdGlvbnNNZXNzYWdlRGlhbG9nIGRpYWxvZyA9IG51bGw7CgkJCQlTdHJpbmdbXSBpdGVtcyA9IG51bGw7CgkJCQlpZiAoYnJlYWtwb2ludHNPcHRpb24pIHsKCQkJCQlpdGVtcyA9IG5ldyBTdHJpbmdbXSB7CgkJCQkJCU1lc3NhZ2VzLmRpYWxvZ01vZGVXYXJuaW5nUmVzdGFydCwKCQkJCQkJTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdCcmVha3BvaW50cywKCQkJCQkJTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdDb250aW51ZQoJCQkJCX07CgkJCQl9IGVsc2UgewoJCQkJCWl0ZW1zID0gbmV3IFN0cmluZ1tdIHsKCQkJCQkJTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdSZXN0YXJ0LAoJCQkJCQlNZXNzYWdlcy5kaWFsb2dNb2RlV2FybmluZ0NvbnRpbnVlCgkJCQkJfTsKCQkJCX0KCQkJCQoJCQkJZGlhbG9nID0gbmV3IE9wdGlvbnNNZXNzYWdlRGlhbG9nKHNoZWxsLCB0aXRsZSwgbWVzc2FnZSwgaXRlbXMpOwoJCQkJaVswXSA9IGRpYWxvZy5vcGVuKCk7CgkJCQkKCQkJCWlmIChkaWFsb2cuaXNSZW1lbWJlcigpKSB7CgkJCQkJaWYgKGJyZWFrcG9pbnRzT3B0aW9uKSB7CgkJCQkJCWlmIChpWzBdID09IDApCgkJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldExhdW5jaE1vZGUyKFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREUyX1JFU1RBUlQpOwoJCQkJCQllbHNlIGlmIChpWzBdID09IDEpCgkJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldExhdW5jaE1vZGUyKFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREUyX0RJU0FCTEVfQlJFQUtQT0lOVFMpOwoJCQkJCQllbHNlIGlmIChpWzBdID09IDIpCgkJCQkJCQlTZXJ2ZXJVSVBsdWdpbi5nZXRQcmVmZXJlbmNlcygpLnNldExhdW5jaE1vZGUyKFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREUyX0NPTlRJTlVFKTsKCQkJCQl9IGVsc2UgewoJCQkJCQlpZiAoaVswXSA9PSAwKQoJCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRMYXVuY2hNb2RlKFNlcnZlclVJUHJlZmVyZW5jZXMuTEFVTkNIX01PREVfUkVTVEFSVCk7CgkJCQkJCWVsc2UgaWYgKGlbMF0gPT0gMSkKCQkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0TGF1bmNoTW9kZShTZXJ2ZXJVSVByZWZlcmVuY2VzLkxBVU5DSF9NT0RFX0NPTlRJTlVFKTsKCQkJCQl9CgkJCQl9CgkJCX0KCQl9KTsKCQlyZXR1cm4gaVswXTsKCX0KCgkvKioKCSAqIE9wZW4gYW4gb3B0aW9ucyBkaWFsb2cuCgkgKiAKCSAqIEBwYXJhbSBzaGVsbAoJICogQHJldHVybiBhIGRpYWxvZyByZXR1cm4gY29uc3RhbnQKCSAqLwoJcHJvdGVjdGVkIHN0YXRpYyBpbnQgb3BlbkJyZWFrcG9pbnREaWFsb2coZmluYWwgU2hlbGwgc2hlbGwpIHsKCQlpbnQgY3VycmVudCA9IFNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuZ2V0RW5hYmxlQnJlYWtwb2ludHMoKTsKCQlpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLkVOQUJMRV9CUkVBS1BPSU5UU19BTFdBWVMpCgkJCXJldHVybiAwOwoJCWVsc2UgaWYgKGN1cnJlbnQgPT0gU2VydmVyVUlQcmVmZXJlbmNlcy5FTkFCTEVfQlJFQUtQT0lOVFNfTkVWRVIpCgkJCXJldHVybiAxOwoJCQoJCWZpbmFsIGludFtdIGkgPSBuZXcgaW50WzFdOwoJCXNoZWxsLmdldERpc3BsYXkoKS5zeW5jRXhlYyhuZXcgUnVubmFibGUoKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCU9wdGlvbnNNZXNzYWdlRGlhbG9nIGRpYWxvZyA9IG5ldyBPcHRpb25zTWVzc2FnZURpYWxvZyhzaGVsbCwKCQkJCQkJTWVzc2FnZXMud2l6RGVidWdPblNlcnZlclRpdGxlLCBNZXNzYWdlcy5kaWFsb2dCcmVha3BvaW50cywgbmV3IFN0cmluZ1tdIHsKCQkJCQkJTWVzc2FnZXMuZGlhbG9nQnJlYWtwb2ludHNSZWVuYWJsZSwgTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdDb250aW51ZX0pOwoJCQkJaVswXSA9IGRpYWxvZy5vcGVuKCk7CgkJCQlpZiAoZGlhbG9nLmlzUmVtZW1iZXIoKSkgewoJCQkJCWlmIChpWzBdID09IDApCgkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0RW5hYmxlQnJlYWtwb2ludHMoU2VydmVyVUlQcmVmZXJlbmNlcy5FTkFCTEVfQlJFQUtQT0lOVFNfQUxXQVlTKTsKCQkJCQllbHNlIGlmIChpWzBdID09IDEpCgkJCQkJCVNlcnZlclVJUGx1Z2luLmdldFByZWZlcmVuY2VzKCkuc2V0RW5hYmxlQnJlYWtwb2ludHMoU2VydmVyVUlQcmVmZXJlbmNlcy5FTkFCTEVfQlJFQUtQT0lOVFNfTkVWRVIpOwoJCQkJfQoJCQl9CgkJfSk7CgkJcmV0dXJuIGlbMF07Cgl9CgoJLyoqCgkgKiBPcGVuIGEgcmVzdGFydCBvcHRpb25zIGRpYWxvZy4KCSAqIAoJICogQHBhcmFtIHNoZWxsCgkgKiBAcmV0dXJuIGEgZGlhbG9nIHJldHVybiBjb25zdGFudAoJICovCglwcm90ZWN0ZWQgc3RhdGljIGludCBvcGVuUmVzdGFydERpYWxvZyhmaW5hbCBTaGVsbCBzaGVsbCkgewoJCWludCBjdXJyZW50ID0gU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5nZXRSZXN0YXJ0KCk7CgkJaWYgKGN1cnJlbnQgPT0gU2VydmVyVUlQcmVmZXJlbmNlcy5SRVNUQVJUX0FMV0FZUykKCQkJcmV0dXJuIDA7CgkJZWxzZSBpZiAoY3VycmVudCA9PSBTZXJ2ZXJVSVByZWZlcmVuY2VzLlJFU1RBUlRfTkVWRVIpCgkJCXJldHVybiAxOwoJCQoJCWZpbmFsIGludFtdIGkgPSBuZXcgaW50WzFdOwoJCXNoZWxsLmdldERpc3BsYXkoKS5zeW5jRXhlYyhuZXcgUnVubmFibGUoKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCU9wdGlvbnNNZXNzYWdlRGlhbG9nIGRpYWxvZyA9IG5ldyBPcHRpb25zTWVzc2FnZURpYWxvZyhzaGVsbCwKCQkJCQkJTWVzc2FnZXMuZGVmYXVsdERpYWxvZ1RpdGxlLCBNZXNzYWdlcy5kaWFsb2dSZXN0YXJ0LCBuZXcgU3RyaW5nW10gewoJCQkJCQlNZXNzYWdlcy5kaWFsb2dSZXN0YXJ0UmVzdGFydCwgTWVzc2FnZXMuZGlhbG9nUmVzdGFydENvbnRpbnVlfSk7CgkJCQlpWzBdID0gZGlhbG9nLm9wZW4oKTsKCQkJCWlmIChkaWFsb2cuaXNSZW1lbWJlcigpKSB7CgkJCQkJaWYgKGlbMF0gPT0gMCkKCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRSZXN0YXJ0KFNlcnZlclVJUHJlZmVyZW5jZXMuUkVTVEFSVF9BTFdBWVMpOwoJCQkJCWVsc2UgaWYgKGlbMF0gPT0gMSkKCQkJCQkJU2VydmVyVUlQbHVnaW4uZ2V0UHJlZmVyZW5jZXMoKS5zZXRSZXN0YXJ0KFNlcnZlclVJUHJlZmVyZW5jZXMuUkVTVEFSVF9ORVZFUik7CgkJCQl9CgkJCX0KCQl9KTsKCQlyZXR1cm4gaVswXTsKCX0KCgkvKioKCSAqIFRoZSBkZWxlZ2F0aW5nIGFjdGlvbiBoYXMgYmVlbiBwZXJmb3JtZWQuIEltcGxlbWVudAoJICogdGhpcyBtZXRob2QgdG8gZG8gdGhlIGFjdHVhbCB3b3JrLgoJICoKCSAqIEBwYXJhbSBhY3Rpb24gYWN0aW9uIHByb3h5IHRoYXQgaGFuZGxlcyB0aGUgcHJlc2VudGF0aW9uCgkgKiBwb3J0aW9uIG9mIHRoZSBwbHVnaW4gYWN0aW9uCgkgKi8KCXB1YmxpYyB2b2lkIHJ1bihJQWN0aW9uIGFjdGlvbikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlJ1bm5pbmcgb24gU2VydmVyLi4uIik7CgkJdHJ5IHsKCQkJcnVuKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiUnVuIG9uIFNlcnZlciBFcnJvciIsIGUpOwoJCX0KCX0KCglwcm90ZWN0ZWQgYm9vbGVhbiBpc0VuYWJsZWQoKSB7CgkJdHJ5IHsKCQkJQm9vbGVhbiBiID0gZ2xvYmFsTGF1bmNoTW9kZS5nZXQoZ2V0TGF1bmNoTW9kZSgpKTsKCQkJcmV0dXJuIGIuYm9vbGVhblZhbHVlKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIHN0YXJ0IG1vZGUgdGhhdCB0aGUgc2VydmVyIHNob3VsZCB1c2UuCgkgKi8KCXByb3RlY3RlZCBTdHJpbmcgZ2V0TGF1bmNoTW9kZSgpIHsKCQlyZXR1cm4gbGF1bmNoTW9kZTsKCX0KCgkvKioKCSAqIFNldCB0aGUgbGF1bmNoIG1vZGUuCgkgKiAKCSAqIEBwYXJhbSBsYXVuY2hNb2RlIGEge0BsaW5rIElMYXVuY2hNYW5hZ2VyfSBsYXVuY2ggbW9kZQoJICovCglwdWJsaWMgdm9pZCBzZXRMYXVuY2hNb2RlKFN0cmluZyBsYXVuY2hNb2RlKSB7CgkJdGhpcy5sYXVuY2hNb2RlID0gbGF1bmNoTW9kZTsKCX0KCgkvKioKCSAqIERldGVybWluZSB3aGljaCBjbGllbnRzIGNhbiBhY3Qgb24gdGhlIGN1cnJlbnQgc2VsZWN0aW9uLgoJICoKCSAqIEBwYXJhbSBhY3Rpb24gYWN0aW9uIHByb3h5IHRoYXQgaGFuZGxlcyBwcmVzZW50YXRpb24KCSAqICAgIHBvcnRpb24gb2YgdGhlIHBsdWdpbiBhY3Rpb24KCSAqIEBwYXJhbSBzZWwgY3VycmVudCBzZWxlY3Rpb24gaW4gdGhlIGRlc2t0b3AKCSAqLwoJcHVibGljIHZvaWQgc2VsZWN0aW9uQ2hhbmdlZChJQWN0aW9uIGFjdGlvbiwgSVNlbGVjdGlvbiBzZWwpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICI+IHNlbGVjdGlvbkNoYW5nZWQiKTsKCQlzZWxlY3Rpb24gPSBudWxsOwoJCWxvbmcgdGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCWlmIChzZWwgPT0gbnVsbCB8fCBzZWwuaXNFbXB0eSgpIHx8ICEoc2VsIGluc3RhbmNlb2YgSVN0cnVjdHVyZWRTZWxlY3Rpb24pKSB7CgkJCWFjdGlvbi5zZXRFbmFibGVkKGZhbHNlKTsKCQkJZ2xvYmFsU2VsZWN0aW9uID0gbnVsbDsKCQkJcmV0dXJuOwoJCX0KCQkKCQlJU3RydWN0dXJlZFNlbGVjdGlvbiBzZWxlY3QgPSAoSVN0cnVjdHVyZWRTZWxlY3Rpb24pIHNlbDsKCQlJdGVyYXRvciBpdGVyYXRvciA9IHNlbGVjdC5pdGVyYXRvcigpOwoJCWlmIChpdGVyYXRvci5oYXNOZXh0KCkpCgkJCXNlbGVjdGlvbiA9IGl0ZXJhdG9yLm5leHQoKTsKCQlpZiAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7IC8vIG1vcmUgdGhhbiBvbmUgc2VsZWN0aW9uIChzaG91bGQgbmV2ZXIgaGFwcGVuKQoJCQlhY3Rpb24uc2V0RW5hYmxlZChmYWxzZSk7CgkJCXNlbGVjdGlvbiA9IG51bGw7CgkJCWdsb2JhbFNlbGVjdGlvbiA9IG51bGw7CgkJCXJldHVybjsKCQl9CgkJCgkJaWYgKHNlbGVjdGlvbiAhPSBnbG9iYWxTZWxlY3Rpb24pIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiU2VsZWN0aW9uOiAiICsgc2VsZWN0aW9uKTsKCQkJaWYgKHNlbGVjdGlvbiAhPSBudWxsKQkKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlNlbGVjdGlvbiB0eXBlOiAiICsgc2VsZWN0aW9uLmdldENsYXNzKCkuZ2V0TmFtZSgpKTsKCQkJZ2xvYmFsU2VsZWN0aW9uID0gc2VsZWN0aW9uOwoJCQlnbG9iYWxMYXVuY2hNb2RlID0gbmV3IEhhc2hNYXA8U3RyaW5nLCBCb29sZWFuPigpOwoJCQlpZiAoIVNlcnZlclBsdWdpbi5oYXNNb2R1bGVBcnRpZmFjdChnbG9iYWxTZWxlY3Rpb24pKSB7CgkJCQlhY3Rpb24uc2V0RW5hYmxlZChmYWxzZSk7CgkJCQlyZXR1cm47CgkJCX0KCQkJCgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgImNoZWNraW5nIGZvciBtb2R1bGUgYXJ0aWZhY3QiKTsKCQkJLy8gVE9ETyAtIG11bHRpcGxlIG1vZHVsZSBhcnRpZmFjdHMKCQkJSU1vZHVsZUFydGlmYWN0W10gbW9kdWxlQXJ0aWZhY3RzID0gU2VydmVyUGx1Z2luLmdldE1vZHVsZUFydGlmYWN0cyhnbG9iYWxTZWxlY3Rpb24pOwoJCQlJTW9kdWxlQXJ0aWZhY3QgbW9kdWxlQXJ0aWZhY3QgPSBudWxsOwoJCQlpZiAobW9kdWxlQXJ0aWZhY3RzICE9IG51bGwpCgkJCQltb2R1bGVBcnRpZmFjdCA9IG1vZHVsZUFydGlmYWN0c1swXTsKCQkJCgkJCUlNb2R1bGUgbW9kdWxlID0gbnVsbDsKCQkJaWYgKG1vZHVsZUFydGlmYWN0ICE9IG51bGwpCgkJCQltb2R1bGUgPSBtb2R1bGVBcnRpZmFjdC5nZXRNb2R1bGUoKTsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAibW9kdWxlQXJ0aWZhY3Q9ICIgKyBtb2R1bGVBcnRpZmFjdCArICIsIG1vZHVsZT0gIiArIG1vZHVsZSk7CgkJCWlmIChtb2R1bGUgIT0gbnVsbCkKCQkJCWZpbmRHbG9iYWxMYXVuY2hNb2Rlcyhtb2R1bGUpOwoJCQllbHNlIHsKCQkJCWdsb2JhbExhdW5jaE1vZGUucHV0KElMYXVuY2hNYW5hZ2VyLlJVTl9NT0RFLCBuZXcgQm9vbGVhbih0cnVlKSk7CgkJCQlnbG9iYWxMYXVuY2hNb2RlLnB1dChJTGF1bmNoTWFuYWdlci5ERUJVR19NT0RFLCBuZXcgQm9vbGVhbih0cnVlKSk7CgkJCQlnbG9iYWxMYXVuY2hNb2RlLnB1dChJTGF1bmNoTWFuYWdlci5QUk9GSUxFX01PREUsIG5ldyBCb29sZWFuKHRydWUpKTsKCQkJfQoJCX0KCQkKCQlhY3Rpb24uc2V0RW5hYmxlZChpc0VuYWJsZWQoKSk7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiPCBzZWxlY3Rpb25DaGFuZ2VkICIgKyAoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCkgLSB0aW1lKSk7Cgl9CgoJLyoqCgkgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlcmUgaXMgYSBzZXJ2ZXIgZmFjdG9yeSBhdmFpbGFibGUgZm9yIHRoZSBnaXZlbiBtb2R1bGUKCSAqIGFuZCB0aGUgdmFyaW91cyBzdGFydCBtb2Rlcy4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmluZEdsb2JhbExhdW5jaE1vZGVzKElNb2R1bGUgbW9kdWxlKSB7CgkJSVNlcnZlclR5cGVbXSBzZXJ2ZXJUeXBlcyA9IFNlcnZlckNvcmUuZ2V0U2VydmVyVHlwZXMoKTsKCQlpZiAoc2VydmVyVHlwZXMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IHNlcnZlclR5cGVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCUlTZXJ2ZXJUeXBlIHR5cGUgPSBzZXJ2ZXJUeXBlc1tpXTsKCQkJCWlmIChpc1ZhbGlkU2VydmVyVHlwZSh0eXBlLCBtb2R1bGUpKSB7CgkJCQkJZm9yIChieXRlIGIgPSAwOyBiIDwgbGF1bmNoTW9kZXMubGVuZ3RoOyBiKyspIHsKCQkJCQkJaWYgKHR5cGUuc3VwcG9ydHNMYXVuY2hNb2RlKGxhdW5jaE1vZGVzW2JdKSkgewoJCQkJCQkJZ2xvYmFsTGF1bmNoTW9kZS5wdXQobGF1bmNoTW9kZXNbYl0sIG5ldyBCb29sZWFuKHRydWUpKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCX0KCgkvKioKCSAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgZ2l2ZW4gc2VydmVyIHR5cGUgY2FuIGxhdW5jaCB0aGUgbW9kdWxlLiAKCSAqLwoJcHJvdGVjdGVkIGJvb2xlYW4gaXNWYWxpZFNlcnZlclR5cGUoSVNlcnZlclR5cGUgdHlwZSwgSU1vZHVsZSBtb2R1bGUpIHsKCQl0cnkgewoJCQlJUnVudGltZVR5cGUgcnVudGltZVR5cGUgPSB0eXBlLmdldFJ1bnRpbWVUeXBlKCk7CgkJCVNlcnZlclV0aWwuaXNTdXBwb3J0ZWRNb2R1bGUocnVudGltZVR5cGUuZ2V0TW9kdWxlVHlwZXMoKSwgbW9kdWxlLmdldE1vZHVsZVR5cGUoKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQlyZXR1cm4gdHJ1ZTsKCX0KfQ==