cGFja2FnZSBvcmcuZWNsaXBzZS51aS5leHRlcm5hbHRvb2xzLmludGVybmFsLnVpOwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQ29weXJpZ2h0IChjKSAyMDAyIElCTSBDb3JwLiBhbmQgb3RoZXJzLgpBbGwgcmlnaHRzIHJlc2VydmVkLiCgIFRoaXMgcHJvZ3JhbSBhbmQgdGhlIGFjY29tcGFueWluZyBtYXRlcmlhbHMKYXJlIG1hZGUgYXZhaWxhYmxlIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgQ29tbW9uIFB1YmxpYyBMaWNlbnNlIHYwLjUKd2hpY2ggYWNjb21wYW5pZXMgdGhpcyBkaXN0cmlidXRpb24sIGFuZCBpcyBhdmFpbGFibGUgYXQKaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9sZWdhbC9jcGwtdjA1Lmh0bWwKoApDb250cmlidXRvcnM6CioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCmltcG9ydCBqYXZhLnV0aWwuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLio7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS5kaWFsb2dzLio7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS52aWV3ZXJzLio7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS53aW5kb3cuV2luZG93OwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LlNXVDsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC5wcm9ncmFtLlByb2dyYW07CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QubGF5b3V0Lio7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLio7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuZ3JhcGhpY3MuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLio7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5kaWFsb2dzLlByb3BlcnR5UGFnZTsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLmV4dGVybmFsdG9vbHMuaW50ZXJuYWwuY29yZS4qOwoKLyoqCiAqIFByb3BlcnR5IHBhZ2UgdG8gYWRkIGV4dGVybmFsIHRvb2xzIGluIGJldHdlZW4gYnVpbGRlcnMuCiAqLwpwdWJsaWMgZmluYWwgY2xhc3MgQnVpbGRlclByb3BlcnR5UGFnZSBleHRlbmRzIFByb3BlcnR5UGFnZSB7Cglwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgQlVJTERFUl9UQUJMRV9XSURUSCA9IDI1MDsKCglwcml2YXRlIFRhYmxlIGJ1aWxkZXJUYWJsZTsKCXByaXZhdGUgQnV0dG9uIHVwQnV0dG9uLCBkb3duQnV0dG9uLCBuZXdCdXR0b24sIGVkaXRCdXR0b24sIHJlbW92ZUJ1dHRvbjsKCXByaXZhdGUgQXJyYXlMaXN0IGltYWdlc1RvRGlzcG9zZSA9IG5ldyBBcnJheUxpc3QoKTsKCXByaXZhdGUgSW1hZ2UgYW50SW1hZ2UsIGJ1aWxkZXJJbWFnZSwgZXh0ZXJuYWxUb29sSW1hZ2UsIGludmFsaWRCdWlsZFRvb2xJbWFnZTsKCgkvKioKCSAqIENyZWF0ZXMgYW4gaW5pdGlhbGl6ZWQgcHJvcGVydHkgcGFnZQoJICovCglwdWJsaWMgQnVpbGRlclByb3BlcnR5UGFnZSgpIHsKCQlzdXBlcigpOwoJCW5vRGVmYXVsdEFuZEFwcGx5QnV0dG9uKCk7Cgl9CgoJLyoqCgkgKiBBZGQgdGhlIHByb2plY3QncyBidWlsZCB0byB0aGUgdGFibGUgdmlld2VyLgoJICovCglwcml2YXRlIHZvaWQgYWRkQnVpbGRlcnNUb1RhYmxlKCkgewoJCUlQcm9qZWN0IHByb2plY3QgPSBnZXRJbnB1dFByb2plY3QoKTsKCQlpZiAocHJvamVjdCA9PSBudWxsKSB7CgkJCXJldHVybjsKCQl9CgkJLy9hZGQgYnVpbGQgc3BlYyBlbnRyaWVzIHRvIHRoZSB0YWJsZQoJCXRyeSB7CgkJCUlDb21tYW5kW10gY29tbWFuZHMgPSBwcm9qZWN0LmdldERlc2NyaXB0aW9uKCkuZ2V0QnVpbGRTcGVjKCk7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgY29tbWFuZHMubGVuZ3RoOyBpKyspIHsKCQkJCWFkZENvbW1hbmQoY29tbWFuZHNbaV0sIC0xLCBmYWxzZSk7CgkJCX0KCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGUpIHsKCQkJaGFuZGxlRXhjZXB0aW9uKGUpOwoJCX0KCX0KCQoJLyoqCgkgKiBBZGRzIGEgYnVpbGQgY29tbWFuZCB0byB0aGUgdGFibGUgdmlld2VyLgoJICogCgkgKiBAcGFyYW0gY29tbWFuZCB0aGUgY29tbWFuZCB0byBiZSBhZGRlZAoJICogQHBhcmFtIHBvc2l0aW9uIHRoZSBpbnNlcnRpb24gcG9zaXRpb24sIG9yIC0xIHRvIGFkZCBhdCB0aGUgZW5kCgkgKiBAcGFyYW0gc2VsZWN0IHdoZXRoZXIgdG8gc2VsZWN0IHRoZSBuZXdseSBjcmVhdGVkIGl0ZW0uCgkgKi8KCXByaXZhdGUgdm9pZCBhZGRDb21tYW5kKElDb21tYW5kIGNvbW1hbmQsIGludCBwb3NpdGlvbiwgYm9vbGVhbiBzZWxlY3QpIHsKCQlUYWJsZUl0ZW0gbmV3SXRlbTsKCQlpZiAocG9zaXRpb24gPCAwKSB7CgkJCW5ld0l0ZW0gPSBuZXcgVGFibGVJdGVtKGJ1aWxkZXJUYWJsZSwgU1dULk5PTkUpOwoJCX0gZWxzZSB7CgkJCW5ld0l0ZW0gPSBuZXcgVGFibGVJdGVtKGJ1aWxkZXJUYWJsZSwgU1dULk5PTkUsIHBvc2l0aW9uKTsKCQl9CgkJbmV3SXRlbS5zZXREYXRhKGNvbW1hbmQpOwoJCXVwZGF0ZUNvbW1hbmRJdGVtKG5ld0l0ZW0sIGNvbW1hbmQpOwoJCWlmIChzZWxlY3QpIGJ1aWxkZXJUYWJsZS5zZXRTZWxlY3Rpb24ocG9zaXRpb24pOwoJfQoJCgkvKioKCSAqIENvbmZpZ3VyZXMgYW5kIGNyZWF0ZXMgYSBuZXcgYnVpbGQgY29tbWFuZAoJICogdGhhdCBpbnZva2VzIGFuIGV4dGVybmFsIHRvb2wuICBSZXR1cm5zIHRoZSBuZXcgY29tbWFuZCwKCSAqIG9yIDxjb2RlPm51bGw8L2NvZGU+IGlmIG5vIGNvbW1hbmQgd2FzIGNyZWF0ZWQuCgkgKi8KCXByaXZhdGUgSUNvbW1hbmQgY3JlYXRlVG9vbCgpIHsKCQl0cnkgewoJCQlFZGl0RGlhbG9nIGRpYWxvZzsKCQkJZGlhbG9nID0gbmV3IEVkaXREaWFsb2coZ2V0U2hlbGwoKSwgbnVsbCk7CgkJCWlmIChkaWFsb2cub3BlbigpID09IFdpbmRvdy5PSykgewoJCQkJRXh0ZXJuYWxUb29sIHRvb2wgPSBkaWFsb2cuZ2V0RXh0ZXJuYWxUb29sKCk7CgkJCQlJQ29tbWFuZCBjb21tYW5kID0gZ2V0SW5wdXRQcm9qZWN0KCkuZ2V0RGVzY3JpcHRpb24oKS5uZXdDb21tYW5kKCk7CgkJCQlyZXR1cm4gdG9vbC50b0J1aWxkQ29tbWFuZChjb21tYW5kKTsKCQkJfSBlbHNlIHsKCQkJCXJldHVybiBudWxsOwkKCQkJfQoJCX0gY2F0Y2goQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCWhhbmRsZUV4Y2VwdGlvbihlKTsKCQkJcmV0dXJuIG51bGw7CgkJfQkJCgl9CgkKCS8qKgoJICogRWRpdHMgYW4gZXhpc2l0aW5nIGJ1aWxkIGNvbW1hbmQgdGhhdCBpbnZva2VzIGFuIGV4dGVybmFsIHRvb2wuCgkgKi8KCXByaXZhdGUgdm9pZCBlZGl0VG9vbChJQ29tbWFuZCBjb21tYW5kKSB7CgkJRXh0ZXJuYWxUb29sIHRvb2wgPSBFeHRlcm5hbFRvb2wuZnJvbUFyZ3VtZW50TWFwKGNvbW1hbmQuZ2V0QXJndW1lbnRzKCkpOwoJCWlmICh0b29sID09IG51bGwpCgkJCXJldHVybjsKCQlFZGl0RGlhbG9nIGRpYWxvZzsKCQlkaWFsb2cgPSBuZXcgRWRpdERpYWxvZyhnZXRTaGVsbCgpLCB0b29sKTsKCQlpZiAoZGlhbG9nLm9wZW4oKSA9PSBXaW5kb3cuT0spIHsKCQkJdG9vbCA9IGRpYWxvZy5nZXRFeHRlcm5hbFRvb2woKTsKCQkJdG9vbC50b0J1aWxkQ29tbWFuZChjb21tYW5kKTsKCQl9Cgl9CgkKCS8qKgoJICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIGJ1dHRvbiB3aXRoIHRoZSBnaXZlbiBsYWJlbCwgaWQsIGFuZCBlbmFibGVtZW50LgoJICovCglwcml2YXRlIEJ1dHRvbiBjcmVhdGVCdXR0b24oQ29tcG9zaXRlIHBhcmVudCwgU3RyaW5nIGxhYmVsKSB7CgkJQnV0dG9uIGJ1dHRvbiA9IG5ldyBCdXR0b24ocGFyZW50LCBTV1QuUFVTSCk7CgkJR3JpZERhdGEgZGF0YSA9IG5ldyBHcmlkRGF0YSgpOwoJCWRhdGEud2lkdGhIaW50ID0gY29udmVydEhvcml6b250YWxETFVzVG9QaXhlbHMoSURpYWxvZ0NvbnN0YW50cy5CVVRUT05fV0lEVEgpOwoJCWRhdGEuaGVpZ2h0SGludCA9IGNvbnZlcnRWZXJ0aWNhbERMVXNUb1BpeGVscyhJRGlhbG9nQ29uc3RhbnRzLkJVVFRPTl9IRUlHSFQpOwoJCWJ1dHRvbi5zZXRMYXlvdXREYXRhKGRhdGEpOyAKCQlidXR0b24uc2V0VGV4dChsYWJlbCk7CgkJYnV0dG9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCWJ1dHRvbi5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJaGFuZGxlQnV0dG9uUHJlc3NlZCgoQnV0dG9uKWUud2lkZ2V0KTsKCQkJfQoJCX0pOwoJCXJldHVybiBidXR0b247Cgl9CgkKCS8qIChub24tSmF2YWRvYykKCSAqIE1ldGhvZCBkZWNsYXJlZCBvbiBQcmVmZXJlbmNlUGFnZS4KCSAqLwoJcHJvdGVjdGVkIENvbnRyb2wgY3JlYXRlQ29udGVudHMoQ29tcG9zaXRlIHBhcmVudCkgewoJCWV4dGVybmFsVG9vbEltYWdlID0gRXh0ZXJuYWxUb29sc1BsdWdpbi5nZXREZWZhdWx0KCkuZ2V0SW1hZ2VEZXNjcmlwdG9yKEV4dGVybmFsVG9vbHNQbHVnaW4uSU1HX0VYVEVSTkFMX1RPT0wpLmNyZWF0ZUltYWdlKCk7CgkJYW50SW1hZ2UgPSBFeHRlcm5hbFRvb2xzUGx1Z2luLmdldERlZmF1bHQoKS5nZXRJbWFnZURlc2NyaXB0b3IoRXh0ZXJuYWxUb29sc1BsdWdpbi5JTUdfQU5UX1RPT0wpLmNyZWF0ZUltYWdlKCk7CgkJYnVpbGRlckltYWdlID0gRXh0ZXJuYWxUb29sc1BsdWdpbi5nZXREZWZhdWx0KCkuZ2V0SW1hZ2VEZXNjcmlwdG9yKEV4dGVybmFsVG9vbHNQbHVnaW4uSU1HX0JVSUxERVIpLmNyZWF0ZUltYWdlKCk7CgkJaW52YWxpZEJ1aWxkVG9vbEltYWdlID0gRXh0ZXJuYWxUb29sc1BsdWdpbi5nZXREZWZhdWx0KCkuZ2V0SW1hZ2VEZXNjcmlwdG9yKEV4dGVybmFsVG9vbHNQbHVnaW4uSU1HX0lOVkFMSURfQlVJTERfVE9PTCkuY3JlYXRlSW1hZ2UoKTsKCgkJaW1hZ2VzVG9EaXNwb3NlLmFkZChleHRlcm5hbFRvb2xJbWFnZSk7CgkJaW1hZ2VzVG9EaXNwb3NlLmFkZChhbnRJbWFnZSk7CgkJaW1hZ2VzVG9EaXNwb3NlLmFkZChidWlsZGVySW1hZ2UpOwoJCWltYWdlc1RvRGlzcG9zZS5hZGQoaW52YWxpZEJ1aWxkVG9vbEltYWdlKTsKCQkKCQlDb21wb3NpdGUgdG9wTGV2ZWwgPSBuZXcgQ29tcG9zaXRlKHBhcmVudCwgU1dULk5PTkUpOwoJCUdyaWRMYXlvdXQgbGF5b3V0ID0gbmV3IEdyaWRMYXlvdXQoKTsKCQlsYXlvdXQubWFyZ2luSGVpZ2h0ID0gMDsKCQlsYXlvdXQubWFyZ2luV2lkdGggPSAwOwoJCXRvcExldmVsLnNldExheW91dChsYXlvdXQpOwoJCXRvcExldmVsLnNldExheW91dERhdGEobmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfQk9USCkpOwoJCQoJCUxhYmVsIGRlc2NyaXB0aW9uID0gbmV3IExhYmVsKHRvcExldmVsLCBTV1QuV1JBUCk7CgkJZGVzY3JpcHRpb24uc2V0VGV4dChUb29sTWVzc2FnZXMuZ2V0U3RyaW5nKCJCdWlsZGVyUHJvcGVydHlQYWdlLmRlc2NyaXB0aW9uIikpOyAvLyROT04tTkxTLTEkCgkJZGVzY3JpcHRpb24uc2V0TGF5b3V0RGF0YShuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKSk7CgkKCQlDb21wb3NpdGUgdGFibGVBbmRCdXR0b25zID0gbmV3IENvbXBvc2l0ZSh0b3BMZXZlbCwgU1dULk5PTkUpOwoJCXRhYmxlQW5kQnV0dG9ucy5zZXRMYXlvdXREYXRhKG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0JPVEgpKTsKCQlsYXlvdXQgPSBuZXcgR3JpZExheW91dCgpOwoJCWxheW91dC5tYXJnaW5IZWlnaHQgPSAwOwoJCWxheW91dC5tYXJnaW5XaWR0aCA9IDA7CgkJbGF5b3V0Lm51bUNvbHVtbnMgPSAyOwoJCXRhYmxlQW5kQnV0dG9ucy5zZXRMYXlvdXQobGF5b3V0KTsKCQoJCS8vIHRhYmxlIG9mIGJ1aWxkZXJzIGFuZCB0b29scwkJCgkJYnVpbGRlclRhYmxlID0gbmV3IFRhYmxlKHRhYmxlQW5kQnV0dG9ucywgU1dULlNJTkdMRSB8IFNXVC5IX1NDUk9MTCB8IFNXVC5WX1NDUk9MTCB8IFNXVC5GVUxMX1NFTEVDVElPTiB8IFNXVC5CT1JERVIpOwoJCUdyaWREYXRhIGRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9CT1RIKTsKCQlkYXRhLndpZHRoSGludCA9IEJVSUxERVJfVEFCTEVfV0lEVEg7CgkJYnVpbGRlclRhYmxlLnNldExheW91dERhdGEoZGF0YSk7CgkJYnVpbGRlclRhYmxlLmFkZFNlbGVjdGlvbkxpc3RlbmVyKG5ldyBTZWxlY3Rpb25BZGFwdGVyKCkgewoJCQlwdWJsaWMgdm9pZCB3aWRnZXRTZWxlY3RlZChTZWxlY3Rpb25FdmVudCBlKSB7CgkJCQloYW5kbGVUYWJsZVNlbGVjdGlvbkNoYW5nZWQoKTsKCQkJfQoJCX0pOwoJCQoJCS8vYnV0dG9uIGFyZWEKCQlDb21wb3NpdGUgYnV0dG9uQXJlYSA9IG5ldyBDb21wb3NpdGUodGFibGVBbmRCdXR0b25zLCBTV1QuTk9ORSk7CgkJbGF5b3V0ID0gbmV3IEdyaWRMYXlvdXQoKTsKCQlsYXlvdXQubWFyZ2luSGVpZ2h0ID0gMDsKCQlsYXlvdXQubWFyZ2luV2lkdGggPSAwOwoJCWJ1dHRvbkFyZWEuc2V0TGF5b3V0KGxheW91dCk7CgkJYnV0dG9uQXJlYS5zZXRMYXlvdXREYXRhKG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX1ZFUlRJQ0FMKSk7CgkJbmV3QnV0dG9uID0gY3JlYXRlQnV0dG9uKGJ1dHRvbkFyZWEsIFRvb2xNZXNzYWdlcy5nZXRTdHJpbmcoIkJ1aWxkZXJQcm9wZXJ0eVBhZ2UubmV3QnV0dG9uIikpOyAvLyROT04tTkxTLTEkCgkJZWRpdEJ1dHRvbiA9IGNyZWF0ZUJ1dHRvbihidXR0b25BcmVhLCBUb29sTWVzc2FnZXMuZ2V0U3RyaW5nKCJCdWlsZGVyUHJvcGVydHlQYWdlLmVkaXRCdXR0b24iKSk7IC8vJE5PTi1OTFMtMSQKCQlyZW1vdmVCdXR0b24gPSBjcmVhdGVCdXR0b24oYnV0dG9uQXJlYSwgVG9vbE1lc3NhZ2VzLmdldFN0cmluZygiQnVpbGRlclByb3BlcnR5UGFnZS5yZW1vdmVCdXR0b24iKSk7IC8vJE5PTi1OTFMtMSQKCQlMYWJlbCBidXR0b25TcGFjZXIgPSBuZXcgTGFiZWwoYnV0dG9uQXJlYSwgU1dULkxFRlQpOwoJCXVwQnV0dG9uID0gY3JlYXRlQnV0dG9uKGJ1dHRvbkFyZWEsIFRvb2xNZXNzYWdlcy5nZXRTdHJpbmcoIkJ1aWxkZXJQcm9wZXJ0eVBhZ2UudXBCdXR0b24iKSk7IC8vJE5PTi1OTFMtMSQKCQlkb3duQnV0dG9uID0gY3JlYXRlQnV0dG9uKGJ1dHRvbkFyZWEsIFRvb2xNZXNzYWdlcy5nZXRTdHJpbmcoIkJ1aWxkZXJQcm9wZXJ0eVBhZ2UuZG93bkJ1dHRvbiIpKTsgLy8kTk9OLU5MUy0xJAoJCgkJbmV3QnV0dG9uLnNldEVuYWJsZWQodHJ1ZSk7CgkJCgkJLy9wb3B1bGF0ZSB3aWRnZXQgY29udGVudHMJCgkJYWRkQnVpbGRlcnNUb1RhYmxlKCk7CgkJCgkJcmV0dXJuIHRvcExldmVsOwoJfQoJCgkvKiAobm9uLUphdmFkb2MpCgkgKiBNZXRob2QgZGVjbGFyZWQgb24gRGlhbG9nUGFnZS4KCSAqLwoJcHVibGljIHZvaWQgZGlzcG9zZSgpIHsKCQlzdXBlci5kaXNwb3NlKCk7CgkJZm9yIChJdGVyYXRvciBpID0gaW1hZ2VzVG9EaXNwb3NlLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewoJCQlJbWFnZSBpbWFnZSA9IChJbWFnZSkgaS5uZXh0KCk7CgkJCWltYWdlLmRpc3Bvc2UoKTsKCQl9CgkJaW1hZ2VzVG9EaXNwb3NlLmNsZWFyKCk7Cgl9CgkKCS8qKgoJICogUmV0dXJucyB0aGUgcHJvamVjdCB0aGF0IGlzIHRoZSBpbnB1dCBmb3IgdGhpcyBwcm9wZXJ0eSBwYWdlLAoJICogb3IgPGNvZGU+bnVsbDwvY29kZT4uCgkgKi8KCXByaXZhdGUgSVByb2plY3QgZ2V0SW5wdXRQcm9qZWN0KCkgewoJCUlBZGFwdGFibGUgZWxlbWVudCA9IGdldEVsZW1lbnQoKTsKCQlpZiAoZWxlbWVudCBpbnN0YW5jZW9mIElQcm9qZWN0KSB7CgkJCXJldHVybiAoSVByb2plY3QpZWxlbWVudDsKCQl9CgkJT2JqZWN0IHJlc291cmNlID0gZWxlbWVudC5nZXRBZGFwdGVyKElSZXNvdXJjZS5jbGFzcyk7CgkJaWYgKHJlc291cmNlIGluc3RhbmNlb2YgSVByb2plY3QpIHsKCQkJcmV0dXJuIChJUHJvamVjdClyZXNvdXJjZTsKCQl9CgkJcmV0dXJuIG51bGw7Cgl9CgkKCS8qKgoJICogT25lIG9mIHRoZSBidXR0b25zIGhhcyBiZWVuIHByZXNzZWQsIGFjdCBhY2NvcmRpbmdseS4KCSAqLwoJcHJpdmF0ZSB2b2lkIGhhbmRsZUJ1dHRvblByZXNzZWQoQnV0dG9uIGJ1dHRvbikgewoJCWlmIChidXR0b24gPT0gbmV3QnV0dG9uKSB7CgkJCUlDb21tYW5kIG5ld0NvbW1hbmQgPSBjcmVhdGVUb29sKCk7CgkJCWlmIChuZXdDb21tYW5kICE9IG51bGwpIHsKCQkJCWludCBpbnNlcnRQb3NpdGlvbiA9IGJ1aWxkZXJUYWJsZS5nZXRTZWxlY3Rpb25JbmRleCgpICsgMTsKCQkJCWFkZENvbW1hbmQobmV3Q29tbWFuZCwgaW5zZXJ0UG9zaXRpb24sIHRydWUpOwoJCQl9CgkJfSBlbHNlIGlmIChidXR0b24gPT0gZWRpdEJ1dHRvbikgewoJCQlUYWJsZUl0ZW1bXSBzZWxlY3Rpb24gPSBidWlsZGVyVGFibGUuZ2V0U2VsZWN0aW9uKCk7CgkJCWlmIChzZWxlY3Rpb24gIT0gbnVsbCkgewoJCQkJZWRpdFRvb2woKElDb21tYW5kKXNlbGVjdGlvblswXS5nZXREYXRhKCkpOwoJCQkJdXBkYXRlQ29tbWFuZEl0ZW0oc2VsZWN0aW9uWzBdLChJQ29tbWFuZClzZWxlY3Rpb25bMF0uZ2V0RGF0YSgpKTsKCQkJfQoJCX0gZWxzZSBpZiAoYnV0dG9uID09IHJlbW92ZUJ1dHRvbikgewoJCQlUYWJsZUl0ZW1bXSBzZWxlY3Rpb24gPSBidWlsZGVyVGFibGUuZ2V0U2VsZWN0aW9uKCk7CgkJCWlmIChzZWxlY3Rpb24gIT0gbnVsbCkgewoJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzZWxlY3Rpb24ubGVuZ3RoOyBpKyspIHsKCQkJCQlzZWxlY3Rpb25baV0uZGlzcG9zZSgpOwoJCQkJfQoJCQl9CgkJfSBlbHNlIGlmIChidXR0b24gPT0gdXBCdXR0b24pIHsKCQkJbW92ZVNlbGVjdGlvblVwKCk7CgkJfSBlbHNlIGlmIChidXR0b24gPT0gZG93bkJ1dHRvbikgewoJCQltb3ZlU2VsZWN0aW9uRG93bigpOwoJCX0KCQloYW5kbGVUYWJsZVNlbGVjdGlvbkNoYW5nZWQoKTsKCQlidWlsZGVyVGFibGUuc2V0Rm9jdXMoKTsKCX0KCQoJLyoqCgkgKiBIYW5kbGVzIHVuZXhwZWN0ZWQgaW50ZXJuYWwgZXhjZXB0aW9ucwoJICovCglwcml2YXRlIHZvaWQgaGFuZGxlRXhjZXB0aW9uKEV4Y2VwdGlvbiBlKSB7CgkJSVN0YXR1cyBzdGF0dXM7CgkJaWYgKGUgaW5zdGFuY2VvZiBDb3JlRXhjZXB0aW9uKSB7CgkJCXN0YXR1cyA9ICgoQ29yZUV4Y2VwdGlvbillKS5nZXRTdGF0dXMoKTsKCQl9IGVsc2UgewoJCQlzdGF0dXMgPSBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIEV4dGVybmFsVG9vbHNQbHVnaW4uUExVR0lOX0lELCAwLCBUb29sTWVzc2FnZXMuZ2V0U3RyaW5nKCJCdWlsZGVyUHJvcGVydHlQYWdlLnN0YXR1c01lc3NhZ2UiKSwgZSk7IC8vJE5PTi1OTFMtMSQKCQl9CgkJRXJyb3JEaWFsb2cub3BlbkVycm9yKAoJCQlnZXRTaGVsbCgpLAoJCQlUb29sTWVzc2FnZXMuZ2V0U3RyaW5nKCJCdWlsZGVyUHJvcGVydHlQYWdlLmVycm9yVGl0bGUiKSwgLy8kTk9OLU5MUy0xJAoJCQlUb29sTWVzc2FnZXMuZ2V0U3RyaW5nKCJCdWlsZGVyUHJvcGVydHlQYWdlLmVycm9yTWVzc2FnZSIpLCAvLyROT04tTkxTLTEkCgkJCXN0YXR1cyk7Cgl9CgkKCS8qKgoJICogVGhlIHVzZXIgaGFzIHNlbGVjdGVkIGEgZGlmZmVyZW50IGJ1aWxkZXIgaW4gdGFibGUuCgkgKiBVcGRhdGUgYnV0dG9uIGVuYWJsZW1lbnQuCgkgKi8KCXByaXZhdGUgdm9pZCBoYW5kbGVUYWJsZVNlbGVjdGlvbkNoYW5nZWQoKSB7CgkJbmV3QnV0dG9uLnNldEVuYWJsZWQodHJ1ZSk7CgkJVGFibGVJdGVtW10gaXRlbXMgPSBidWlsZGVyVGFibGUuZ2V0U2VsZWN0aW9uKCk7CgkJaWYgKGl0ZW1zICE9IG51bGwgJiYgaXRlbXMubGVuZ3RoID09IDEpIHsKCQkJVGFibGVJdGVtIGl0ZW0gPSBpdGVtc1swXTsKCQkJSUNvbW1hbmQgYnVpbGRDb21tYW5kID0gKElDb21tYW5kKWl0ZW0uZ2V0RGF0YSgpOwoJCQlpZiAoYnVpbGRDb21tYW5kLmdldEJ1aWxkZXJOYW1lKCkuZXF1YWxzKEV4dGVybmFsVG9vbHNCdWlsZGVyLklEKSkgewoJCQkJZWRpdEJ1dHRvbi5zZXRFbmFibGVkKHRydWUpOwoJCQkJcmVtb3ZlQnV0dG9uLnNldEVuYWJsZWQodHJ1ZSk7CgkJCQlpbnQgc2VsZWN0aW9uID0gYnVpbGRlclRhYmxlLmdldFNlbGVjdGlvbkluZGV4KCk7CgkJCQlpbnQgbWF4ID0gYnVpbGRlclRhYmxlLmdldEl0ZW1Db3VudCgpOwoJCQkJdXBCdXR0b24uc2V0RW5hYmxlZChzZWxlY3Rpb24gIT0gMCk7CgkJCQlkb3duQnV0dG9uLnNldEVuYWJsZWQoc2VsZWN0aW9uIDwgbWF4LTEpOwoJCQkJcmV0dXJuOwoJCQl9CgkJfQoJCS8vaW4gYWxsIG90aGVyIGNhc2VzIHdlIGNhbid0IGRvIGFueSBvZiB0aGVzZS4KCQllZGl0QnV0dG9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCXJlbW92ZUJ1dHRvbi5zZXRFbmFibGVkKGZhbHNlKTsKCQl1cEJ1dHRvbi5zZXRFbmFibGVkKGZhbHNlKTsKCQlkb3duQnV0dG9uLnNldEVuYWJsZWQoZmFsc2UpOwoJfQoJCgkvKioKCSAqIE1vdmVzIGFuIGVudHJ5IGluIHRoZSBidWlsZGVyIHRhYmxlIHRvIHRoZSBnaXZlbiBpbmRleC4KCSAqLwoJcHJpdmF0ZSB2b2lkIG1vdmUoVGFibGVJdGVtIGl0ZW0sIGludCBpbmRleCkgewoJCU9iamVjdCBkYXRhID0gaXRlbS5nZXREYXRhKCk7CgkJU3RyaW5nIHRleHQgPSBpdGVtLmdldFRleHQoKTsKCQlJbWFnZSBpbWFnZT0gaXRlbS5nZXRJbWFnZSgpOwoJCWl0ZW0uZGlzcG9zZSgpOwoJCVRhYmxlSXRlbSBuZXdJdGVtID0gbmV3IFRhYmxlSXRlbShidWlsZGVyVGFibGUsIFNXVC5OT05FLCBpbmRleCk7CgkJbmV3SXRlbS5zZXREYXRhKGRhdGEpOwoJCW5ld0l0ZW0uc2V0VGV4dCh0ZXh0KTsKCQluZXdJdGVtLnNldEltYWdlKGltYWdlKTsKCX0KCQoJLyoqCgkgKiBNb3ZlIHRoZSBjdXJyZW50IHNlbGVjdGlvbiBpbiB0aGUgYnVpbGQgbGlzdCBkb3duLgoJICovCglwcml2YXRlIHZvaWQgbW92ZVNlbGVjdGlvbkRvd24oKSB7CgkJLy8gT25seSBkbyB0aGlzIG9wZXJhdGlvbiBvbiBhIHNpbmdsZSBzZWxlY3Rpb24KCQlpZiAoYnVpbGRlclRhYmxlLmdldFNlbGVjdGlvbkNvdW50KCkgPT0gMSkgewoJCQlpbnQgY3VycmVudEluZGV4ID0gYnVpbGRlclRhYmxlLmdldFNlbGVjdGlvbkluZGV4KCk7CgkJCWlmIChjdXJyZW50SW5kZXggPCBidWlsZGVyVGFibGUuZ2V0SXRlbUNvdW50KCkgLSAxKSB7CgkJCQltb3ZlKGJ1aWxkZXJUYWJsZS5nZXRJdGVtKGN1cnJlbnRJbmRleCksIGN1cnJlbnRJbmRleCsxKTsKCQkJCWJ1aWxkZXJUYWJsZS5zZXRTZWxlY3Rpb24oY3VycmVudEluZGV4KzEpOwoJCQl9CgkJfQoJfQoJCgkvKioKCSAqIE1vdmUgdGhlIGN1cnJlbnQgc2VsZWN0aW9uIGluIHRoZSBidWlsZCBsaXN0IHVwLgoJICovCglwcml2YXRlIHZvaWQgbW92ZVNlbGVjdGlvblVwKCkgewoJCWludCBjdXJyZW50SW5kZXggPSBidWlsZGVyVGFibGUuZ2V0U2VsZWN0aW9uSW5kZXgoKTsKCQkvLyBPbmx5IGRvIHRoaXMgb3BlcmF0aW9uIG9uIGEgc2luZ2xlIHNlbGVjdGlvbgoJCWlmIChjdXJyZW50SW5kZXggPiAwICYmIGJ1aWxkZXJUYWJsZS5nZXRTZWxlY3Rpb25Db3VudCgpID09IDEpIHsKCQkJbW92ZShidWlsZGVyVGFibGUuZ2V0SXRlbShjdXJyZW50SW5kZXgpLCBjdXJyZW50SW5kZXgtMSk7CgkJCWJ1aWxkZXJUYWJsZS5zZXRTZWxlY3Rpb24oY3VycmVudEluZGV4LTEpOwoJCX0KCX0KCQoJLyogKG5vbi1KYXZhZG9jKQoJICogTWV0aG9kIGRlY2xhcmVkIG9uIElQcmVmZXJlbmNlUGFnZS4KCSAqLwoJcHVibGljIGJvb2xlYW4gcGVyZm9ybU9rKCkgewoJCS8vZ2V0IGFsbCB0aGUgYnVpbGQgY29tbWFuZHMKCQlpbnQgbnVtQ29tbWFuZHMgPSBidWlsZGVyVGFibGUuZ2V0SXRlbUNvdW50KCk7CgkJSUNvbW1hbmRbXSBjb21tYW5kcyA9IG5ldyBJQ29tbWFuZFtudW1Db21tYW5kc107CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBudW1Db21tYW5kczsgaSsrKSB7CgkJCWNvbW1hbmRzW2ldID0gKElDb21tYW5kKWJ1aWxkZXJUYWJsZS5nZXRJdGVtKGkpLmdldERhdGEoKTsKCQl9CgkJLy9zZXQgdGhlIGJ1aWxkIHNwZWMKCQlJUHJvamVjdCBwcm9qZWN0ID0gZ2V0SW5wdXRQcm9qZWN0KCk7CgkJdHJ5IHsKCQkJSVByb2plY3REZXNjcmlwdGlvbiBkZXNjID0gcHJvamVjdC5nZXREZXNjcmlwdGlvbigpOwoJCQlkZXNjLnNldEJ1aWxkU3BlYyhjb21tYW5kcyk7CgkJCXByb2plY3Quc2V0RGVzY3JpcHRpb24oZGVzYywgbnVsbCk7CgkJfSBjYXRjaChDb3JlRXhjZXB0aW9uIGUpIHsKCQkJaGFuZGxlRXhjZXB0aW9uKGUpOwoJCX0KCQlyZXR1cm4gc3VwZXIucGVyZm9ybU9rKCk7Cgl9CgkKCS8qKgoJICogVXBkYXRlIHRoZSB0YWJsZSBpdGVtIHdpdGggdGhlIGdpdmVuIGJ1aWxkIGNvbW1hbmQKCSAqLwoJcHJpdmF0ZSB2b2lkIHVwZGF0ZUNvbW1hbmRJdGVtKFRhYmxlSXRlbSBpdGVtLCBJQ29tbWFuZCBjb21tYW5kKSB7CgkJU3RyaW5nIGJ1aWxkZXJJRCA9IGNvbW1hbmQuZ2V0QnVpbGRlck5hbWUoKTsKCQlpZiAoYnVpbGRlcklELmVxdWFscyhFeHRlcm5hbFRvb2xzQnVpbGRlci5JRCkpIHsKCQkJRXh0ZXJuYWxUb29sIHRvb2wgPSBFeHRlcm5hbFRvb2wuZnJvbUFyZ3VtZW50TWFwKGNvbW1hbmQuZ2V0QXJndW1lbnRzKCkpOwoJCQlpZiAodG9vbCA9PSBudWxsKSB7CgkJCQlpdGVtLnNldFRleHQoVG9vbE1lc3NhZ2VzLmdldFN0cmluZygiQnVpbGRlclByb3BlcnR5UGFnZS5pbnZhbGlkQnVpbGRUb29sIikpOyAvLyROT04tTkxTLTEkCgkJCQlpdGVtLnNldEltYWdlKGludmFsaWRCdWlsZFRvb2xJbWFnZSk7CgkJCQlyZXR1cm47CgkJCX0KCQkJaXRlbS5zZXRUZXh0KHRvb2wuZ2V0TmFtZSgpKTsKCQkJaWYgKHRvb2wuVE9PTF9UWVBFX0FOVC5lcXVhbHModG9vbC5nZXRUeXBlKCkpKSB7CgkJCQlpdGVtLnNldEltYWdlKGFudEltYWdlKTsKCQkJfSBlbHNlIHsKCQkJCWl0ZW0uc2V0SW1hZ2UoZXh0ZXJuYWxUb29sSW1hZ2UpOwoJCQl9CgkJfSBlbHNlIHsKCQkJLy8gR2V0IHRoZSBodW1hbi1yZWFkYWJsZSBuYW1lIG9mIHRoZSBidWlsZGVyCgkJCUlFeHRlbnNpb24gZXh0ZW5zaW9uID0gUGxhdGZvcm0uZ2V0UGx1Z2luUmVnaXN0cnkoKS5nZXRFeHRlbnNpb24oUmVzb3VyY2VzUGx1Z2luLlBJX1JFU09VUkNFUywgCVJlc291cmNlc1BsdWdpbi5QVF9CVUlMREVSUywgYnVpbGRlcklEKTsKCQkJU3RyaW5nIGJ1aWxkZXJOYW1lOwoJCQlpZiAoZXh0ZW5zaW9uICE9IG51bGwpCgkJCQlidWlsZGVyTmFtZSA9IGV4dGVuc2lvbi5nZXRMYWJlbCgpOwoJCQllbHNlCgkJCQlidWlsZGVyTmFtZSA9IFRvb2xNZXNzYWdlcy5mb3JtYXQoIkJ1aWxkZXJQcm9wZXJ0eVBhZ2UubWlzc2luZ0J1aWxkZXIiLCBuZXcgT2JqZWN0W10ge2J1aWxkZXJJRH0pOyAvLyROT04tTkxTLTEkCgkJCWl0ZW0uc2V0VGV4dChidWlsZGVyTmFtZSk7CgkJCWl0ZW0uc2V0SW1hZ2UoYnVpbGRlckltYWdlKTsKCQl9Cgl9Cn0K