cGFja2FnZSBvcmcuZWNsaXBzZS51aS5leHRlcm5hbHRvb2xzLmludGVybmFsLnVpOwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQ29weXJpZ2h0IChjKSAyMDAyIElCTSBDb3JwLiBhbmQgb3RoZXJzLgpBbGwgcmlnaHRzIHJlc2VydmVkLiCgIFRoaXMgcHJvZ3JhbSBhbmQgdGhlIGFjY29tcGFueWluZyBtYXRlcmlhbHMKYXJlIG1hZGUgYXZhaWxhYmxlIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgQ29tbW9uIFB1YmxpYyBMaWNlbnNlIHYwLjUKd2hpY2ggYWNjb21wYW5pZXMgdGhpcyBkaXN0cmlidXRpb24sIGFuZCBpcyBhdmFpbGFibGUgYXQKaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9sZWdhbC9jcGwtdjA1Lmh0bWwKoApDb250cmlidXRvcnM6CioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCmltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwoKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmRpYWxvZ3MuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLndpbmRvdy5XaW5kb3c7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuU1dUOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LmV2ZW50cy4qOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LmxheW91dC4qOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLmV4dGVybmFsdG9vbHMuaW50ZXJuYWwuY29yZS4qOwppbXBvcnQgb3JnLmVjbGlwc2UudWkuaGVscC5Xb3JrYmVuY2hIZWxwOwoKLyoqCiAqIERpYWxvZyBib3ggdG8gYWRkLCByZW1vdmUsIGFuZCBlZGl0IGV4dGVybmFsIHRvb2xzLgogKi8KcHVibGljIGNsYXNzIENvbmZpZ3VyYXRpb25EaWFsb2cgZXh0ZW5kcyBUaXRsZUFyZWFEaWFsb2cgewoJLy8gTWluaW11bSBoZWlnaHQgaW4gY2hhcnMgb2YgdGhlIGRldGFpbHMgdGV4dCBib3guCglwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgREVUQUlMU19IRUlHSFQgPSA1OwoJCglwcml2YXRlIExpc3RWaWV3ZXIgbGlzdFZpZXdlcjsKCXByaXZhdGUgQnV0dG9uIG5ld0J1dHRvbjsKCXByaXZhdGUgQnV0dG9uIGVkaXRCdXR0b247Cglwcml2YXRlIEJ1dHRvbiByZW1vdmVCdXR0b247Cglwcml2YXRlIEJ1dHRvbiB1cEJ1dHRvbjsKCXByaXZhdGUgQnV0dG9uIGRvd25CdXR0b247Cglwcml2YXRlIFRleHQgZGV0YWlsVGV4dDsKCXByaXZhdGUgRXh0ZXJuYWxUb29sIGN1cnJlbnRTZWxlY3Rpb247Cglwcml2YXRlIEFycmF5TGlzdCB0b29sczsKCgkvKioKCSAqIEluc3RhbnRpYXRlIGEgbmV3IGV4dGVybmFsIHRvb2wgY29uZmlndXJhdGlvbiBkaWFsb2cuCgkgKgoJICogQHBhcmFtIHBhcmVudFNoZWxsIHRoZSBwYXJlbnQgU1dUIHNoZWxsCgkgKi8KCXB1YmxpYyBDb25maWd1cmF0aW9uRGlhbG9nKFNoZWxsIHBhcmVudFNoZWxsKSB7CgkJc3VwZXIocGFyZW50U2hlbGwpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIE1ldGhvZCBkZWNsYXJlZCBpbiBXaW5kb3cuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGNvbmZpZ3VyZVNoZWxsKFNoZWxsIHNoZWxsKSB7CgkJc3VwZXIuY29uZmlndXJlU2hlbGwoc2hlbGwpOwoJCXNoZWxsLnNldFRleHQoVG9vbE1lc3NhZ2VzLmdldFN0cmluZygiQ29uZmlndXJhdGlvbkRpYWxvZy5zaGVsbFRpdGxlIikpOyAvLyROT04tTkxTLTEkCgkJV29ya2JlbmNoSGVscC5zZXRIZWxwKAoJCQlzaGVsbCwKCQkJSUhlbHBDb250ZXh0SWRzLkNPTkZJR1VSRV9ESUFMT0cpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIE1ldGhvZCBkZWNsYXJlZCBvbiBEaWFsb2cuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGNyZWF0ZUJ1dHRvbnNGb3JCdXR0b25CYXIoQ29tcG9zaXRlIHBhcmVudCkgewoJCWNyZWF0ZUJ1dHRvbihwYXJlbnQsIElEaWFsb2dDb25zdGFudHMuT0tfSUQsIElEaWFsb2dDb25zdGFudHMuT0tfTEFCRUwsIHRydWUpOwoJCWNyZWF0ZUJ1dHRvbihwYXJlbnQsIElEaWFsb2dDb25zdGFudHMuQ0FOQ0VMX0lELCBJRGlhbG9nQ29uc3RhbnRzLkNBTkNFTF9MQUJFTCwgZmFsc2UpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIE1ldGhvZCBkZWNsYXJlZCBvbiBEaWFsb2cuCgkgKi8KCXByb3RlY3RlZCBDb250cm9sIGNyZWF0ZURpYWxvZ0FyZWEoQ29tcG9zaXRlIHBhcmVudCkgewoJCXRvb2xzID0gbmV3IEFycmF5TGlzdChFeHRlcm5hbFRvb2xzUGx1Z2luLmdldERlZmF1bHQoKS5nZXRSZWdpc3RyeSgpLmdldEV4dGVybmFsVG9vbHMoKSk7CgkJCgkJQ29tcG9zaXRlIGRpYWxvZ0NvbXAgPSAoQ29tcG9zaXRlKXN1cGVyLmNyZWF0ZURpYWxvZ0FyZWEocGFyZW50KTsKCQkJCQoJCS8vIFNldCB0aXRsZSBhbmQgbWVzc2FnZSBub3cgdGhhdCB0aGUgY29udHJvbHMgZXhpc3QKCQlzZXRUaXRsZShUb29sTWVzc2FnZXMuZ2V0U3RyaW5nKCJDb25maWd1cmF0aW9uRGlhbG9nLmRpYWxvZ1RpdGxlIikpOyAvLyROT04tTkxTLTEkCgkJc2V0TWVzc2FnZShUb29sTWVzc2FnZXMuZ2V0U3RyaW5nKCJDb25maWd1cmF0aW9uRGlhbG9nLmRpYWxvZ01lc3NhZ2UiKSk7IC8vJE5PTi1OTFMtMSQKCQlzZXRUaXRsZUltYWdlKEV4dGVybmFsVG9vbHNQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldEltYWdlRGVzY3JpcHRvcihFeHRlcm5hbFRvb2xzUGx1Z2luLklNR19XSVpCQU5fRVhURVJOQUxfVE9PTFMpLmNyZWF0ZUltYWdlKCkpOwoJCQkKCQkvLyBCdWlsZCB0aGUgdG9wIGNvbnRhaW5lcgoJCUNvbXBvc2l0ZSB0b3BDb21wID0gbmV3IENvbXBvc2l0ZShkaWFsb2dDb21wLCBTV1QuTk9ORSk7CgkJR3JpZExheW91dCBsYXlvdXQgPSBuZXcgR3JpZExheW91dCgpOwoJCWxheW91dC5tYXJnaW5IZWlnaHQgPSA1OwoJCWxheW91dC5tYXJnaW5XaWR0aCA9IDU7CgkJdG9wQ29tcC5zZXRMYXlvdXQobGF5b3V0KTsKCQlHcmlkRGF0YSBkYXRhID0gbmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfQk9USCk7CgkJdG9wQ29tcC5zZXRMYXlvdXREYXRhKGRhdGEpOwoKCQkvLyBCdWlsZCBtaWRkbGUgY29udGFpbmVyIHdpdGggMiBjb2x1bW5zCgkJQ29tcG9zaXRlIG1pZENvbXAgPSBuZXcgQ29tcG9zaXRlKHRvcENvbXAsIFNXVC5OT05FKTsKCQlsYXlvdXQgPSBuZXcgR3JpZExheW91dCgpOwoJCWxheW91dC5udW1Db2x1bW5zID0gMjsKCQlsYXlvdXQubWFyZ2luSGVpZ2h0ID0gMDsKCQlsYXlvdXQubWFyZ2luV2lkdGggPSAwOwoJCW1pZENvbXAuc2V0TGF5b3V0KGxheW91dCk7CgkJZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0JPVEgpOwoJCW1pZENvbXAuc2V0TGF5b3V0RGF0YShkYXRhKTsKCgkJLy8gQnVpbGQgdGhlIHRvb2xzIGxpc3QKCQlDb21wb3NpdGUgbGlzdENvbXAgPSBuZXcgQ29tcG9zaXRlKG1pZENvbXAsIFNXVC5OT05FKTsKCQlsYXlvdXQgPSBuZXcgR3JpZExheW91dCgpOwoJCWxheW91dC5tYXJnaW5IZWlnaHQgPSAwOwoJCWxheW91dC5tYXJnaW5XaWR0aCA9IDA7CgkJbGlzdENvbXAuc2V0TGF5b3V0KGxheW91dCk7CgkJZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0JPVEgpOwoJCWxpc3RDb21wLnNldExheW91dERhdGEoZGF0YSk7CgoJCUxhYmVsIGxhYmVsID0gbmV3IExhYmVsKGxpc3RDb21wLCBTV1QuTEVGVCk7CgkJbGFiZWwuc2V0TGF5b3V0RGF0YShuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKSk7CgkJbGFiZWwuc2V0VGV4dChUb29sTWVzc2FnZXMuZ2V0U3RyaW5nKCJDb25maWd1cmF0aW9uRGlhbG9nLnRvb2xMaXN0IikpOyAvLyROT04tTkxTLTEkCgkJCgkJbGlzdFZpZXdlciA9IG5ldyBMaXN0Vmlld2VyKGxpc3RDb21wLCBTV1QuU0lOR0xFIHwgU1dULkhfU0NST0xMIHwgU1dULlZfU0NST0xMIHwgU1dULkJPUkRFUik7CgkJbGlzdFZpZXdlci5nZXRMaXN0KCkuc2V0TGF5b3V0RGF0YShuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9CT1RIKSk7CgkJbGlzdFZpZXdlci5zZXRDb250ZW50UHJvdmlkZXIobmV3IFRvb2xDb250ZW50UHJvdmlkZXIoKSk7CgkJbGlzdFZpZXdlci5zZXRMYWJlbFByb3ZpZGVyKG5ldyBUb29sTGFiZWxQcm92aWRlcigpKTsKCQlsaXN0Vmlld2VyLnNldElucHV0KHRvb2xzKTsKCQlsaXN0Vmlld2VyLmFkZERvdWJsZUNsaWNrTGlzdGVuZXIobmV3IElEb3VibGVDbGlja0xpc3RlbmVyKCkgewoJCQlwdWJsaWMgdm9pZCBkb3VibGVDbGljayhEb3VibGVDbGlja0V2ZW50IGV2ZW50KSB7CgkJCQlvcGVuRWRpdFRvb2xEaWFsb2coKTsKCQkJfQoJCX0pOwoKCQkvLyBCdWlsZCB0aGUgYnV0dG9uIGxpc3QKCQlDb21wb3NpdGUgYnV0dG9uQ29tcCA9IG5ldyBDb21wb3NpdGUobWlkQ29tcCwgU1dULk5PTkUpOwoJCWxheW91dCA9IG5ldyBHcmlkTGF5b3V0KCk7CgkJbGF5b3V0Lm1hcmdpbkhlaWdodCA9IDA7CgkJbGF5b3V0Lm1hcmdpbldpZHRoID0gMDsKCQlidXR0b25Db21wLnNldExheW91dChsYXlvdXQpOwoJCWRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9WRVJUSUNBTCk7CgkJYnV0dG9uQ29tcC5zZXRMYXlvdXREYXRhKGRhdGEpOwoKCQlsYWJlbCA9IG5ldyBMYWJlbChidXR0b25Db21wLCBTV1QuTEVGVCk7IC8vIHNwYWNlcgoJCWxhYmVsLnNldExheW91dERhdGEobmV3IEdyaWREYXRhKEdyaWREYXRhLkhPUklaT05UQUxfQUxJR05fRklMTCkpOwoJCW5ld0J1dHRvbiA9IGNyZWF0ZVB1c2hCdXR0b24oYnV0dG9uQ29tcCwgIkNvbmZpZ3VyYXRpb25EaWFsb2cubmV3QnV0dG9uIiwgdHJ1ZSk7IC8vJE5PTi1OTFMtMSQKCQllZGl0QnV0dG9uID0gY3JlYXRlUHVzaEJ1dHRvbihidXR0b25Db21wLCAiQ29uZmlndXJhdGlvbkRpYWxvZy5lZGl0QnV0dG9uIiwgZmFsc2UpOyAvLyROT04tTkxTLTEkCgkJcmVtb3ZlQnV0dG9uID0gY3JlYXRlUHVzaEJ1dHRvbihidXR0b25Db21wLCAiQ29uZmlndXJhdGlvbkRpYWxvZy5yZW1vdmVCdXR0b24iLCBmYWxzZSk7IC8vJE5PTi1OTFMtMSQKCQlsYWJlbCA9IG5ldyBMYWJlbChidXR0b25Db21wLCBTV1QuTEVGVCk7IC8vIHNwYWNlcgoJCWxhYmVsLnNldExheW91dERhdGEobmV3IEdyaWREYXRhKEdyaWREYXRhLkhPUklaT05UQUxfQUxJR05fRklMTCkpOwoJCXVwQnV0dG9uID0gY3JlYXRlUHVzaEJ1dHRvbihidXR0b25Db21wLCAiQ29uZmlndXJhdGlvbkRpYWxvZy51cEJ1dHRvbiIsIGZhbHNlKTsgLy8kTk9OLU5MUy0xJAoJCWRvd25CdXR0b24gPSBjcmVhdGVQdXNoQnV0dG9uKGJ1dHRvbkNvbXAsICJDb25maWd1cmF0aW9uRGlhbG9nLmRvd25CdXR0b24iLCBmYWxzZSk7IC8vJE5PTi1OTFMtMSQKCQkKCQkvLyBCdWlsZCB0aGUgZGV0YWlscyBmaWVsZAoJCWxhYmVsID0gbmV3IExhYmVsKHRvcENvbXAsIFNXVC5MRUZUKTsKCQlsYWJlbC5zZXRUZXh0KFRvb2xNZXNzYWdlcy5nZXRTdHJpbmcoIkNvbmZpZ3VyYXRpb25EaWFsb2cuZGV0YWlscyIpKTsgLy8kTk9OLU5MUy0xJAoJCWxhYmVsLnNldExheW91dERhdGEobmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfSE9SSVpPTlRBTCkpOwoKCQlkZXRhaWxUZXh0ID0gbmV3IFRleHQodG9wQ29tcCwgU1dULldSQVAgfCBTV1QuTVVMVEkgfCBTV1QuVl9TQ1JPTEwgfCBTV1QuQk9SREVSKTsKCQlkZXRhaWxUZXh0LnNldEVkaXRhYmxlKGZhbHNlKTsKCQlHcmlkRGF0YSBncmlkRGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwpOwoJCWdyaWREYXRhLmhlaWdodEhpbnQgPSBjb252ZXJ0SGVpZ2h0SW5DaGFyc1RvUGl4ZWxzKERFVEFJTFNfSEVJR0hUKTsKCQlkZXRhaWxUZXh0LnNldExheW91dERhdGEoZ3JpZERhdGEpOwoJCQoJCS8vIEJ1aWxkIHRoZSBzZXBhcmF0b3IgbGluZQoJCUxhYmVsIHNlcGFyYXRvciA9IG5ldyBMYWJlbCh0b3BDb21wLCBTV1QuSE9SSVpPTlRBTCB8IFNXVC5TRVBBUkFUT1IpOwoJCXNlcGFyYXRvci5zZXRMYXlvdXREYXRhKG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwpKTsKCQkKCQkvLyBGaW5pc2ggc2V0dXAKCQlob29rQnV0dG9uQWN0aW9ucygpOwoJCWhvb2tTdGF0ZVVwZGF0ZXMoKTsKCQkKCQlyZXR1cm4gZGlhbG9nQ29tcDsKCX0KCQoJcHJpdmF0ZSBCdXR0b24gY3JlYXRlUHVzaEJ1dHRvbihDb21wb3NpdGUgcGFyZW50LCBTdHJpbmcgbGFiZWxLZXksIGJvb2xlYW4gZW5hYmxlZCkgewoJCUJ1dHRvbiBidXR0b24gPSBuZXcgQnV0dG9uKHBhcmVudCwgU1dULlBVU0gpOwoJCWJ1dHRvbi5zZXRUZXh0KFRvb2xNZXNzYWdlcy5nZXRTdHJpbmcobGFiZWxLZXkpKTsKCQlidXR0b24uc2V0RW5hYmxlZChlbmFibGVkKTsKCQkKCQlHcmlkRGF0YSBkYXRhID0gbmV3IEdyaWREYXRhKEdyaWREYXRhLkhPUklaT05UQUxfQUxJR05fRklMTCk7CgkJZGF0YS5oZWlnaHRIaW50ID0gY29udmVydFZlcnRpY2FsRExVc1RvUGl4ZWxzKElEaWFsb2dDb25zdGFudHMuQlVUVE9OX0hFSUdIVCk7CgkJaW50IHdpZHRoSGludCA9IGNvbnZlcnRIb3Jpem9udGFsRExVc1RvUGl4ZWxzKElEaWFsb2dDb25zdGFudHMuQlVUVE9OX1dJRFRIKTsKCQlkYXRhLndpZHRoSGludCA9IE1hdGgubWF4KHdpZHRoSGludCwgYnV0dG9uLmNvbXB1dGVTaXplKFNXVC5ERUZBVUxULCBTV1QuREVGQVVMVCwgdHJ1ZSkueCk7CgkJYnV0dG9uLnNldExheW91dERhdGEoZGF0YSk7CgkJCgkJcmV0dXJuIGJ1dHRvbjsKCX0KCQoJLyoqCgkgKiBBZGRzIHRoZSBsaXN0ZW5lcnMgcmVxdWlyZWQgdG8gaGFuZGxlIHRoZSBidXR0b24KCSAqIGFjdGlvbnMKCSAqLwoJcHJpdmF0ZSB2b2lkIGhvb2tCdXR0b25BY3Rpb25zKCkgewoJCW5ld0J1dHRvbi5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJRWRpdERpYWxvZyBkaWFsb2c7CgkJCQlkaWFsb2cgPSBuZXcgRWRpdERpYWxvZyhnZXRTaGVsbCgpLCBudWxsKTsKCQkJCWlmIChkaWFsb2cub3BlbigpID09IFdpbmRvdy5PSykgewoJCQkJCUV4dGVybmFsVG9vbCB0b29sID0gZGlhbG9nLmdldEV4dGVybmFsVG9vbCgpOwoJCQkJCXRvb2xzLmFkZCh0b29sKTsKCQkJCQlsaXN0Vmlld2VyLmFkZCh0b29sKTsKCQkJCQlsaXN0Vmlld2VyLnNldFNlbGVjdGlvbihuZXcgU3RydWN0dXJlZFNlbGVjdGlvbih0b29sKSwgdHJ1ZSk7CgkJCQl9CgkJCX0KCQl9KTsKCgkJZWRpdEJ1dHRvbi5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJb3BlbkVkaXRUb29sRGlhbG9nKCk7CgkJCX0KCQl9KTsKCgkJcmVtb3ZlQnV0dG9uLmFkZFNlbGVjdGlvbkxpc3RlbmVyKG5ldyBTZWxlY3Rpb25BZGFwdGVyKCkgewoJCQlwdWJsaWMgdm9pZCB3aWRnZXRTZWxlY3RlZChTZWxlY3Rpb25FdmVudCBlKSB7CgkJCQl0b29scy5yZW1vdmUoY3VycmVudFNlbGVjdGlvbik7CgkJCQlsaXN0Vmlld2VyLnJlbW92ZShjdXJyZW50U2VsZWN0aW9uKTsKCQkJfQoJCX0pOwoKCQl1cEJ1dHRvbi5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJaW50IGluZGV4ID0gdG9vbHMuaW5kZXhPZihjdXJyZW50U2VsZWN0aW9uKTsKCQkJCWlmIChpbmRleCA8IDEpCgkJCQkJcmV0dXJuOwoJCQkJT2JqZWN0IHRvb2wgPSB0b29scy5nZXQoaW5kZXggLSAxKTsKCQkJCXRvb2xzLnNldChpbmRleCAtIDEsIGN1cnJlbnRTZWxlY3Rpb24pOwoJCQkJdG9vbHMuc2V0KGluZGV4LCB0b29sKTsKCQkJCWxpc3RWaWV3ZXIucmVmcmVzaChmYWxzZSk7CgkJCQl1cGRhdGVVcERvd25CdXR0b25zKCk7CgkJCX0KCQl9KTsKCgkJZG93bkJ1dHRvbi5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJaW50IGluZGV4ID0gdG9vbHMuaW5kZXhPZihjdXJyZW50U2VsZWN0aW9uKTsKCQkJCWlmIChpbmRleCA8IDAgfHwgaW5kZXggPj0gdG9vbHMuc2l6ZSgpIC0gMSkKCQkJCQlyZXR1cm47CgkJCQlPYmplY3QgdG9vbCA9IHRvb2xzLmdldChpbmRleCArIDEpOwoJCQkJdG9vbHMuc2V0KGluZGV4ICsgMSwgY3VycmVudFNlbGVjdGlvbik7CgkJCQl0b29scy5zZXQoaW5kZXgsIHRvb2wpOwoJCQkJbGlzdFZpZXdlci5yZWZyZXNoKGZhbHNlKTsKCQkJCXVwZGF0ZVVwRG93bkJ1dHRvbnMoKTsKCQkJfQoJCX0pOwoJfQoKCS8qKgoJICogQWRkcyBhIGxpc3RlbmVyIHRvIGNvbnRyb2wgYnV0dG9uIGVuYWJsZW1lbnQgYmFzZWQgb24KCSAqIHRoZSBjdXJyZW50IHNlbGVjdGlvbi4KCSAqLwoJcHJpdmF0ZSB2b2lkIGhvb2tTdGF0ZVVwZGF0ZXMoKSB7CgkJbGlzdFZpZXdlci5hZGRTZWxlY3Rpb25DaGFuZ2VkTGlzdGVuZXIobmV3IElTZWxlY3Rpb25DaGFuZ2VkTGlzdGVuZXIoKSB7CgkJCXB1YmxpYyB2b2lkIHNlbGVjdGlvbkNoYW5nZWQoU2VsZWN0aW9uQ2hhbmdlZEV2ZW50IGV2ZW50KSB7CgkJCQljdXJyZW50U2VsZWN0aW9uID0gbnVsbDsKCQkJCWlmIChldmVudC5nZXRTZWxlY3Rpb24oKSBpbnN0YW5jZW9mIElTdHJ1Y3R1cmVkU2VsZWN0aW9uKSB7CgkJCQkJSVN0cnVjdHVyZWRTZWxlY3Rpb24gc2VsID0gKElTdHJ1Y3R1cmVkU2VsZWN0aW9uKSBldmVudC5nZXRTZWxlY3Rpb24oKSA7CgkJCQkJY3VycmVudFNlbGVjdGlvbiA9IChFeHRlcm5hbFRvb2wpc2VsLmdldEZpcnN0RWxlbWVudCgpOwoJCQkJfQoKCQkJCWVkaXRCdXR0b24uc2V0RW5hYmxlZChjdXJyZW50U2VsZWN0aW9uICE9IG51bGwpOwoJCQkJcmVtb3ZlQnV0dG9uLnNldEVuYWJsZWQoY3VycmVudFNlbGVjdGlvbiAhPSBudWxsKTsKCQkJCXVwZGF0ZVVwRG93bkJ1dHRvbnMoKTsKCQkJCXVwZGF0ZURldGFpbHMoKTsKCQkJfQoJCX0pOwoJfQoKCS8qKgoJICogVXBkYXRlIHRoZSBlbmFibGUgc3RhdGUgb2YgdGhlIHVwL2Rvd24gYnV0dG9ucwoJICovCglwcml2YXRlIHZvaWQgdXBkYXRlVXBEb3duQnV0dG9ucygpIHsKCQlpbnQgc2VsSW5kZXggPSBsaXN0Vmlld2VyLmdldExpc3QoKS5nZXRTZWxlY3Rpb25JbmRleCgpOwoJCWludCBpdGVtQ291bnQgPSBsaXN0Vmlld2VyLmdldExpc3QoKS5nZXRJdGVtQ291bnQoKTsKCQl1cEJ1dHRvbi5zZXRFbmFibGVkKGN1cnJlbnRTZWxlY3Rpb24gIT0gbnVsbCAmJiBzZWxJbmRleCA+IDApOwoJCWRvd25CdXR0b24uc2V0RW5hYmxlZChjdXJyZW50U2VsZWN0aW9uICE9IG51bGwgJiYgc2VsSW5kZXggPCBpdGVtQ291bnQgLSAxKTsKCX0KCgkvKioKCSAqIE9wZW5zIHRoZSBlZGl0IGV4dGVybmFsIHRvb2wgZGlhbG9nIG9uCgkgKiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIGV4dGVybmFsIHRvb2wuCgkgKi8KCXByaXZhdGUgdm9pZCBvcGVuRWRpdFRvb2xEaWFsb2coKSB7CgkJaWYgKGN1cnJlbnRTZWxlY3Rpb24gPT0gbnVsbCkKCQkJcmV0dXJuOwoJCUVkaXREaWFsb2cgZGlhbG9nOwoJCWRpYWxvZyA9IG5ldyBFZGl0RGlhbG9nKGdldFNoZWxsKCksIGN1cnJlbnRTZWxlY3Rpb24pOwoJCWRpYWxvZy5vcGVuKCk7CgkJbGlzdFZpZXdlci51cGRhdGUoY3VycmVudFNlbGVjdGlvbiwgbnVsbCk7CgkJdXBkYXRlRGV0YWlscygpOwoJfQoJCgkvKioKCSAqIFVwZGF0ZSB0aGUgZGV0YWlsIGZpZWxkCgkgKi8KCXByaXZhdGUgdm9pZCB1cGRhdGVEZXRhaWxzKCkgewoJCWlmIChjdXJyZW50U2VsZWN0aW9uID09IG51bGwpCgkJCWRldGFpbFRleHQuc2V0VGV4dCgiIik7IC8vJE5PTi1OTFMtMSQKCQllbHNlCgkJCWRldGFpbFRleHQuc2V0VGV4dChUb29sTWVzc2FnZXMuZm9ybWF0KCJDb25maWd1cmF0aW9uRGlhbG9nLmRldGFpbE1lc3NhZ2UiLCBuZXcgT2JqZWN0W10ge2N1cnJlbnRTZWxlY3Rpb24uZ2V0TG9jYXRpb24oKSwgY3VycmVudFNlbGVjdGlvbi5nZXRBcmd1bWVudHMoKSwgY3VycmVudFNlbGVjdGlvbi5nZXRXb3JraW5nRGlyZWN0b3J5KCl9KSk7IC8vJE5PTi1OTFMtMSQKCX0KCQoJLyogKG5vbi1KYXZhZG9jKQoJICogTWV0aG9kIGRlY2xhcmVkIG9uIERpYWxvZy4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgb2tQcmVzc2VkKCkgewoJCUV4dGVybmFsVG9vbHNQbHVnaW4uZ2V0RGVmYXVsdCgpLmdldFJlZ2lzdHJ5KCkuc2V0RXh0ZXJuYWxUb29scyh0b29scyk7CgkJc3VwZXIub2tQcmVzc2VkKCk7Cgl9CgoJCgkvKioKCSAqIEludGVybmFsIGNvbnRlbnQgcHJvdmlkZXIgb2YgZXhpc3RpbmcgdG9vbCB0b29scwoJICovCglwcml2YXRlIGNsYXNzIFRvb2xDb250ZW50UHJvdmlkZXIgaW1wbGVtZW50cyBJU3RydWN0dXJlZENvbnRlbnRQcm92aWRlciB7CgkJcHVibGljIE9iamVjdFtdIGdldEVsZW1lbnRzKE9iamVjdCBpbnB1dEVsZW1lbnQpIHsKCQkJcmV0dXJuIHRvb2xzLnRvQXJyYXkoKTsKCQl9CgoJCXB1YmxpYyB2b2lkIGRpc3Bvc2UoKSB7CgkJfQoKCQlwdWJsaWMgdm9pZCBpbnB1dENoYW5nZWQoVmlld2VyIHZpZXdlciwgT2JqZWN0IG9sZElucHV0LCBPYmplY3QgbmV3SW5wdXQpIHsKCQl9Cgl9CgkKCS8qKgoJICogSW50ZXJuYWwgbGFiZWwgcHJvdmlkZXIgb2YgZXhpc3RpbmcgdG9vbCB0b29scwoJICovCglwcml2YXRlIGNsYXNzIFRvb2xMYWJlbFByb3ZpZGVyIGV4dGVuZHMgTGFiZWxQcm92aWRlciB7CgkJcHVibGljIFN0cmluZyBnZXRUZXh0KE9iamVjdCBlbGVtZW50KSB7CgkJCWlmIChlbGVtZW50IGluc3RhbmNlb2YgRXh0ZXJuYWxUb29sKQoJCQkJcmV0dXJuICgoRXh0ZXJuYWxUb29sKWVsZW1lbnQpLmdldE5hbWUoKTsKCQkJZWxzZQoJCQkJcmV0dXJuICIiOy8vJE5PTi1OTFMtMSQKCQl9Cgl9Cn0K