PT09PT09PT09PT09PT09PT0NCkNvbm5lY3RpbmcgdG8gQUFGDQo9PT09PT09PT09PT09PT09PQ0KDQpNZXRob2RzIHRvIENvbm5lY3QNCj09PT09PT09PT09PT09PT09PQ0KDQqVCUlmIHlvdSBhcmUgYSBTZXJ2bGV0IGluIGEgQ29udGFpbmVyLCB1c2UgQ0FESSBGcmFtZXdvcmsgd2l0aCBBQUYgUGx1Z2luLiAgSXQncyB2ZXJ5IGVhc3ksIGFuZCBpbmNsdWRlcyBCYXNpY0F1dGggZm9yIFNlcnZpY2VzLiAgDQqVCUphdmEgVGVjaG5vbG9naWVzDQqVCVRlY2hub2xvZ2llcyB1c2luZyBTZXJ2bGV0IEZpbHRlcnMNCpUJRE1FMiAoYW5kIG90aGVyIFNlcnZsZXQgQ29udGFpbmVycykgY2FuIHVzZSBTZXJ2bGV0IEZpbHRlcnMNCpUJQW55IFdlYkFwcCBjYW4gcGx1ZyBpbiBDQURJIGFzIGEgU2VydmxldCBGaWx0ZXINCpUJSmV0dHkgY2FuIGF0dGFjaCBhIFNlcnZsZXQgRmlsdGVyIHdpdGggQ29kZSwgb3IgYXMgV2ViQXBwDQqVCVRvbWNhdCA3IGhhcyBhICJWYWx2ZSIgcGx1Z2luLCB3aGljaCBpcyBzaW1pbGFyIGFuZCBzdXBwb3J0ZWQNCpUJVXNlIHRoZSBBQUZMdXIgQ29kZSBkaXJlY3RseSAoc2hvd24pDQqVCUFsbCBKYXZhIFRlY2hub2xvZ2llcyB1dGlsaXplIENvbmZpZ3VyYXRpb24gdG8gc2V0IHdoYXQgU2VjdXJpdHkgZWxlbWVudHMgYXJlIHJlcXVpcmVkDQqVCWV4YW1wbGU6IEdsb2JhbCBMb2dpbiBjYW4gYmUgdHVybmVkIG9uL29mZiwgQUFGIENsaWVudCBuZWVkcyBpbmZvcm1hdGlvbiB0byBjb25uZWN0IHRvIEFBRiBTZXJ2aWNlDQqVCVRoZXJlIGFyZSBzZXZlcmFsIHNwZWNpYWx0eSBjYXNlcywgd2hpY2ggQUFGIGNhbiB3b3JrIHdpdGgsIGluY2x1ZGluZyBlbWJlZGRpbmcgYWxsIHByb3BlcnRpZXMgaW4gYSBXZWIueG1sLCBidXQgdGhlIGVzc2VudGlhbHMgbmVlZGVkIGFyZToNCpUJQ0FESSBKYXJzDQqVCWNhZGkucHJvcGVydGllcyBmaWxlIChjb25maWd1cmVkIHRoZSBzYW1lIGZvciBhbGwgdGVjaG5vbG9naWVzKQ0KlQlFbmNyeXB0IHBhc3N3b3JkcyB3aXRoIGluY2x1ZGVkIENBREkgdGVjaG5vbG9neSwgc28gdGhhdCB0aGVyZSBhcmUgbm8gQ2xlYXIgVGV4dCBQYXNzd29yZHMgaW4gQ29uZmlnIEZpbGVzIChBU1BSKQ0KlQlTZWUgQ0FESSBEZXBsb3ltZW50IG9uIGhvdyB0byBwZXJmb3JtIHRoaXMgd2l0aCBzZXZlcmFsIGRpZmZlcmVudCB0ZWNobm9sb2dpZXMuDQqVCUFBRiBSZXN0ZnVsbHkgKHNlZSBSRVNURnVsIEFQSVMpDQoNCklNUE9SVEFOVDogSWYgRGlyZWN0IFJFU1RGdWwgQVBJIGlzIHVzZWQsIHRoZW4gaXQgaXMgdGhlIENsaWVudCdzIHJlc3BvbnNpYmlsaXR5IHRvIENhY2hlIGFuZCBhdm9pZCBtYWtpbmcgYW4gQUFGIFNlcnZpY2UgQ2FsbHMgdG9vIG9mdGVuDQpFeGFtcGxlOiBBIFRvb2wgbGlrZSBDYXNzYW5kcmEgd2lsbCBhc2sgZm9yIEF1dGhlbnRpY2F0aW9uIGh1bmRyZWRzIG9mIHRpbWVzIGEgc2Vjb25kIGZvciB0aGUgc2FtZSBpZGVudGl0eSBkdXJpbmcgYSB0cmFuc2FjdGlvbi4gIENhbGxpbmcgdGhlIEFBRiBTZXJ2aWNlIGZvciBlYWNoIHdvdWxkIGJlIHNsb3cgZm9yIHRoZSBjbGllbnQsIGFuZCB3YXN0ZWZ1bCBvZiBOZXR3b3JrIGFuZCBBQUYgU2VydmljZSBDYXBhY2l0aWVzLiAgDQpSb2d1ZSBDbGllbnRzIGNhbiBhbmQgd2lsbCBiZSBkZW5pZWQgYWNjZXNzIHRvIEFBRi4NCg0KDQpKMkVFIChTZXJ2bGV0IEZpbHRlcikgTWV0aG9kDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCjEuCVBlciBKMkVFIGRlc2lnbiwgdGhlIEZpbHRlciB3aWxsIGRlbnkgYW55IHVuYXV0aGVudGljYXRlZCBIVFRQL1MgY2FsbDsgdGhlIFNlcnZsZXQgd2lsbCBub3QgZXZlbiBiZSBpbnZva2VkLg0KYS4JVGhlcmVmb3JlLCB0aGUgU2VydmxldCBjYW4gZGVwZW5kIG9uIGFueSB0cmFuc2FjdGlvbiBtYWtpbmcgaXQgdG8gdGhlaXIgY29kZSBzZXQgaXMgQXV0aGVudGljYXRlZC4NCmIuCUlkZW50aXR5IGNhbiBiZSB2aWV3ZWQgYmFzZWQgb24gdGhlIEh0dHBTZXJ2bGV0UmVxdWVzdCBPYmplY3QgKHJlcXVlc3QuZ2V0VXNlclByaW5jaXBhbCgpICkNCjIuCVBlciBKMkVFIGRlc2lnbiwgQUFGIEZpbHRlciBvdmVybG9hZHMgdGhlIEh0dHBTZXJ2bGV0UmVxdWVzdCBmb3IgYSBTdHJpbmcgcmVsYXRlZCB0byAiUm9sZSIuICAocmVxdWVzdC5pc1VzZXJJblJvbGUoIi4uLiIpICkNCmEuCUZvciBBQUYsIGRvIG5vdCBwdXQgaW4gIlJvbGUiLCBidXQgdGhlIHRocmVlIHBhcnRzIG9mIHJlcXVlc3RlZCAiUGVybWlzc2lvbiIsIHNlcGFyYXRlZCBieSAifCIsIGkuZS4gICJvcmcub25hcC5hYWYubXlhcHAubXlwZXJtfG15SW5zdGFuY2V8bXlBY3Rpb24iLg0KMy4JTk9UIFJFUVVJUkVEOiBBbiBhZGRlZCBiZW5lZml0LCBidXQgbm90IHJlcXVpcmVkLCBpcyBhIEpBU1BJIGxpa2UgaW50ZXJmYWNlLCB3aGVyZSB5b3UgY2FuIGFkZCBhbiBBbm5vdGF0aW9uIHRvIHlvdXIgU2VydmxldC4gDQphLglXaGVuIHVzZWQsIG5vIHRyYW5zYWN0aW9uIHdpbGwgY29tZSBpbnRvIHlvdXIgY29kZSBpZiB0aGUgbGlzdGVkIFBlcm1pc3Npb25zIGFyZSBub3QgR3JhbnRlZCB0byB0aGUgSW5jb21pbmcgVHJhbnNhY3Rpb24uICANCmIuCVRoaXMgbWlnaHQgYmUgaGVscGZ1bCBmb3IgY292ZXJpbmcgc2VwYXJhdGUgTWFuYWdlbWVudCBTZXJ2bGV0IGltcGxlbWVudGF0aW9ucy4NCg0KDQoNClNlcnZsZXQgQ29kZSBTbmlwcGV0DQo9PT09PT09PT09PT09PT09PT09PT09PT09DQoNCnB1YmxpYyB2b2lkIHNlcnZpY2UoU2VydmxldFJlcXVlc3QgcmVxLCBTZXJ2bGV0UmVzcG9uc2UgcmVzKSB0aHJvd3MgU2VydmxldEV4Y2VwdGlvbiwgSU9FeGNlcHRpb24gew0KICAgIEh0dHBTZXJ2bGV0UmVxdWVzdCByZXF1ZXN0Ow0KICAgIHRyeSB7DQogICAgICAgIHJlcXVlc3QgPSAoSHR0cFNlcnZsZXRSZXF1ZXN0KXJlcTsNCiAgICB9IGNhdGNoIChDbGFzc0Nhc3RFeGNlcHRpb24gZSkgew0KICAgICAgICB0aHJvdyBuZXcgU2VydmxldEV4Y2VwdGlvbigiT25seSBzZXJ2aW5nIEhUVFAgdG9kYXkiLGUpOw0KICAgIH0NCiAgICAgDQogICAgLy8gTm90ZTogQ0FESSBpcyBPVkVSTE9BRElORyB0aGUgY29uY2VwdCBvZiAiaXNVc2VySW5Sb2xlIi4uIFlvdSBuZWVkIHRvIHRoaW5rICJkb2VzVXNlckhhdmVQZXJtc3Npb24oKSINCiAgICAvLyBBc3N1bWUgdGhhdCB5b3UgaGF2ZSBDUkVBVEVEIGFuZCBHUkFOVEVEIEFuIEFBRiBQZXJtaXNzaW9uIGluIFlPVVIgTmFtZXNwYWNlDQogICAgLy8gRXhhbXBsZSBQZXJtaXNzaW9uOiAgICJvcmcub25hcC5hYWYubXlhcHAubXlQZXJtICogd3JpdGUiDQogDQogICAgLy8gVGhpbmsgaW4geW91ciBoZWFkLCAiRG9lcyB1c2VyIGhhdmUgd3JpdGUgcGVybWlzc2lvbiBvbiBhbnkgaW5zdGFuY2Ugb2Ygb3JnLm9uYXAuYWFmLm15YXBwLm15UGVybQ0KICAgIGlmKHJlcXVlc3QuaXNVc2VySW5Sb2xlKCJvcmcub25hcC5hYWYubXlhcHAubXlQZXJtfCp8d3JpdGUiKSkgeyANCiAgICAgICAgLy8gKioqIERvIHNvbWV0aGluZyBoZXJlIHRoYXQgc29tZW9uZSB3aXRoICJteVBlcm0gd3JpdGUiIHBlcm1pc3Npb25zIGlzIGFsbG93ZWQgdG8gZG8NCiAgICB9IGVsc2Ugew0KICAgICAgICAvLyAqKiogRG8gc29tZXRoaW5nIHJlYXNvbmFibGUgaWYgdXNlciBpcyBkZW5pZWQsIGxpa2UgYW4gRXJyb3IgTWVzc2FnZQ0KICAgIH0NCiANCn0NCg0KSGVyZSBpcyBhIHdvcmtpbmcgVGVzdFNlcnZsZXQsIHdoZXJlIHlvdSBjYW4gcGxheSB3aXRoIGRpZmZlcmVudCBQZXJtaXNzaW9ucyB0aGF0IHlvdSBvd24gb24gdGhlIFVSTCwgaS5lLjoNCmh0dHBzOi8vPHlvdXIgbWFjaGluZTpwb3J0Pi9jYWRpdGVzdC90ZXN0bWU/UEVSTT1vcmcub25hcC5hYWYubXlhcHAubXlQZXJtfCp8d3JpdGUNCg0KU2FtcGxlIFNlcnZsZXQgKFdvcmtpbmcgZXhhbXBsZSkNCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpwYWNrYWdlIG9yZy5vbmFwLmFhZi5jYWRpLmRlYnVnOw0KaW1wb3J0IGphdmEuaW8uRmlsZUlucHV0U3RyZWFtOw0KaW1wb3J0IGphdmEuaW8uSU9FeGNlcHRpb247DQppbXBvcnQgamF2YS5uZXQuSW5ldEFkZHJlc3M7DQppbXBvcnQgamF2YS5uZXQuVW5rbm93bkhvc3RFeGNlcHRpb247DQppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7DQppbXBvcnQgamF2YS51dGlsLk1hcDsNCmltcG9ydCBqYXZhLnV0aWwuTWFwLkVudHJ5Ow0KaW1wb3J0IGphdmEudXRpbC5Qcm9wZXJ0aWVzOw0KaW1wb3J0IGphdmF4LnNlcnZsZXQuU2VydmxldDsNCmltcG9ydCBqYXZheC5zZXJ2bGV0LlNlcnZsZXRDb25maWc7DQppbXBvcnQgamF2YXguc2VydmxldC5TZXJ2bGV0RXhjZXB0aW9uOw0KaW1wb3J0IGphdmF4LnNlcnZsZXQuU2VydmxldFJlcXVlc3Q7DQppbXBvcnQgamF2YXguc2VydmxldC5TZXJ2bGV0UmVzcG9uc2U7DQppbXBvcnQgamF2YXguc2VydmxldC5odHRwLkh0dHBTZXJ2bGV0UmVxdWVzdDsNCmltcG9ydCBvcmcuZWNsaXBzZS5qZXR0eS5zZXJ2ZXIuU2VydmVyOw0KaW1wb3J0IG9yZy5lY2xpcHNlLmpldHR5LnNlcnZlci5TZXJ2ZXJDb25uZWN0b3I7DQppbXBvcnQgb3JnLmVjbGlwc2UuamV0dHkuc2VydmVyLmhhbmRsZXIuQ29udGV4dEhhbmRsZXI7DQppbXBvcnQgb3JnLmVjbGlwc2UuamV0dHkuc2VydmxldC5GaWx0ZXJIb2xkZXI7DQppbXBvcnQgb3JnLmVjbGlwc2UuamV0dHkuc2VydmxldC5GaWx0ZXJNYXBwaW5nOw0KaW1wb3J0IG9yZy5lY2xpcHNlLmpldHR5LnNlcnZsZXQuU2VydmxldENvbnRleHRIYW5kbGVyOw0KaW1wb3J0IG9yZy5lY2xpcHNlLmpldHR5LnNlcnZsZXQuU2VydmxldEhhbmRsZXI7DQppbXBvcnQgb3JnLm9uYXAuYWFmLmNhZGkuZmlsdGVyLkNhZGlGaWx0ZXI7DQppbXBvcnQgb3JnLm9uYXAuYWFmLmNhZGkuZmlsdGVyLlJvbGVzQWxsb3dlZDsNCmltcG9ydCBvcmcub25hcC5hYWYuY2FkaS5qZXR0eS5NaW5pSkFTUElXcmFwOw0KIA0KcHVibGljIGNsYXNzIENTUFNlcnZsZXRUZXN0IHsNCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7DQogICAgICAgIC8vIEdvIGFoZWFkIGFuZCBwcmludCBUZXN0IHJlcG9ydHMgaW4gY2FkaS1jb3JlIGZpcnN0DQogICAgICAgIFRlc3QubWFpbihhcmdzKTsNCiAgICAgICAgU3RyaW5nIGhvc3RuYW1lPW51bGw7DQogICAgICAgIHRyeSB7DQogICAgICAgICAgICBob3N0bmFtZSA9IEluZXRBZGRyZXNzLmdldExvY2FsSG9zdCgpLmdldEhvc3ROYW1lKCk7DQogICAgICAgIH0gY2F0Y2ggKFVua25vd25Ib3N0RXhjZXB0aW9uIGUpIHsNCiAgICAgICAgICAgIGUucHJpbnRTdGFja1RyYWNlKCk7DQogICAgICAgICAgICBTeXN0ZW0uZXhpdCgxKTsNCiAgICAgICAgfQ0KICAgICAgICBQcm9wZXJ0aWVzIHByb3BzID0gbmV3IFByb3BlcnRpZXMoKTsNCiAgICAgICAgTWFwPFN0cmluZyxTdHJpbmc+IG1hcCA9IG5ldyBIYXNoTWFwPFN0cmluZyxTdHJpbmc+KCk7DQogICAgICAgIHRyeSB7DQogICAgICAgICAgICBGaWxlSW5wdXRTdHJlYW0gZmlzID0gbmV3IEZpbGVJbnB1dFN0cmVhbSgicnVuL2NhZGkucHJvcGVydGllcyIpOw0KICAgICAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgICAgICBwcm9wcy5sb2FkKGZpcyk7DQogICAgICAgICAgICAgICAgU3RyaW5nIGtleSx2YWx1ZTsNCiAgICAgICAgICAgICAgICBmb3IoIEVudHJ5PE9iamVjdCwgT2JqZWN0PiBlcyAgOiBwcm9wcy5lbnRyeVNldCgpKSB7DQogICAgICAgICAgICAgICAgICAgIGtleSA9IGVzLmdldEtleSgpLnRvU3RyaW5nKCk7DQogICAgICAgICAgICAgICAgICAgIHZhbHVlID0gZXMuZ2V0VmFsdWUoKS50b1N0cmluZygpOw0KICAgICAgICAgICAgICAgICAgICBtYXAucHV0KGtleSx2YWx1ZSk7DQogICAgICAgICAgICAgICAgICAgIGlmKGtleS5zdGFydHNXaXRoKCJBRlRfIikgfHwga2V5LnN0YXJ0c1dpdGgoIkRNRTIiKSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgU3lzdGVtLnNldFByb3BlcnR5KGtleSx2YWx1ZSk7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9IGZpbmFsbHkgew0KICAgICAgICAgICAgICAgIGZpcy5jbG9zZSgpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9IGNhdGNoKElPRXhjZXB0aW9uIGUpIHsNCiAgICAgICAgICAgIFN5c3RlbS5lcnIucHJpbnRsbigiQ2Fubm90IGxvYWQgcnVuL2NhZGkucHJvcGVydGllcyIpOw0KICAgICAgICAgICAgU3lzdGVtLmV4aXQoMSk7DQogICAgICAgIH0NCiAgICAgICAgU3RyaW5nIHBvcnRTdHIgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoInBvcnQiKTsNCiAgICAgICAgaW50IHBvcnQgPSBwb3J0U3RyPT1udWxsPzgwODA6SW50ZWdlci5wYXJzZUludChwb3J0U3RyKTsNCiAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgIC8vIEFkZCBTZXJ2bGV0SG9sZGVyKHMpIGFuZCBGaWx0ZXIocykgdG8gYSBTZXJ2bGV0SGFuZGxlcg0KICAgICAgICAgICAgU2VydmxldEhhbmRsZXIgc2hhbmQgPSBuZXcgU2VydmxldEhhbmRsZXIoKTsNCiAgICAgICAgICAgICANCiAgICAgICAgICAgIEZpbHRlckhvbGRlciBjZmggPSBuZXcgRmlsdGVySG9sZGVyKENhZGlGaWx0ZXIuY2xhc3MpOw0KICAgICAgICAgICAgY2ZoLnNldEluaXRQYXJhbWV0ZXJzKG1hcCk7DQogICAgICAgICAgICAgDQogICAgICAgICAgICBzaGFuZC5hZGRGaWx0ZXJXaXRoTWFwcGluZyhjZmgsICIvKiIsIEZpbHRlck1hcHBpbmcuQUxMKTsNCiAgICAgICAgICAgIHNoYW5kLmFkZFNlcnZsZXRXaXRoTWFwcGluZyhuZXcgTWluaUpBU1BJV3JhcChNeVNlcnZsZXQuY2xhc3MpLCIvKiIpOw0KICAgICAgICAgICAgLy8gY2FsbCBpbml0aWFsaXplIGFmdGVyIHN0YXJ0DQogICAgICAgICAgICAgDQogICAgICAgICAgICBDb250ZXh0SGFuZGxlciBjaCA9IG5ldyBTZXJ2bGV0Q29udGV4dEhhbmRsZXIoKTsNCiAgICAgICAgICAgIGNoLnNldENvbnRleHRQYXRoKCIvY2FkaXRlc3QiKTsNCiAgICAgICAgICAgIGNoLnNldEhhbmRsZXIoc2hhbmQpOw0KICAgICAgICAgICAgZm9yKCBFbnRyeTxPYmplY3QsT2JqZWN0PiBlcyA6IHByb3BzLmVudHJ5U2V0KCkpIHsNCiAgICAgICAgICAgICAgICBjaC5nZXRJbml0UGFyYW1zKCkucHV0KGVzLmdldEtleSgpLnRvU3RyaW5nKCksIGVzLmdldFZhbHVlKCkudG9TdHJpbmcoKSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICAvL2NoLnNldEVycm9ySGFuZGxlcihuZXcgTXlFcnJvckhhbmRsZXIoKSk7DQogICAgICAgICAgICAgDQogICAgICAgICAgICAvLyBDcmVhdGUgU2VydmVyIGFuZCBBZGQgQ29udGV4dCBIYW5kbGVyDQogICAgICAgICAgICBmaW5hbCBTZXJ2ZXIgc2VydmVyID0gbmV3IFNlcnZlcigpOw0KICAgICAgICAgICAgU2VydmVyQ29ubmVjdG9yIGh0dHAgPSBuZXcgU2VydmVyQ29ubmVjdG9yKHNlcnZlcik7DQogICAgICAgICAgICBodHRwLnNldFBvcnQocG9ydCk7DQogICAgICAgICAgICBzZXJ2ZXIuYWRkQ29ubmVjdG9yKGh0dHApOw0KICAgICAgICAgICAgc2VydmVyLnNldEhhbmRsZXIoY2gpOw0KICAgICAgICAgDQogICAgICAgICAgICAvLyBTdGFydA0KICAgICAgICAgICAgc2VydmVyLnN0YXJ0KCk7DQogICAgICAgICAgICBzaGFuZC5pbml0aWFsaXplKCk7DQogICAgICAgICAgICAgDQogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIlRvIHRlc3QsIHB1dCBodHRwOi8vIisgaG9zdG5hbWUgKyAnOicgKyBwb3J0ICsgIi9jYWRpdGVzdC90ZXN0bWUgaW4gYSBicm93c2VyIG9yICdjdXJsJyIpOw0KICAgICAgICAgICAgLy8gaWYgd2Ugd2VyZSByZWFsbHkgYSBzZXJ2ZXIsIHdlJ2QgYmxvY2sgdGhlIG1haW4gdGhyZWFkIHdpdGggdGhpcyBqb2luLi4uDQogICAgICAgICAgICAvLyBzZXJ2ZXIuam9pbigpOw0KICAgICAgICAgICAgLy8gQnV0Li4uIHNpbmNlIHdlJ3JlIGEgdGVzdCBzZXJ2aWNlLCB3ZSdsbCBibG9jayBvbiBTdGRJbg0KICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJQcmVzcyA8UmV0dXJuPiB0byBlbmQgc2VydmljZS4uLiIpOw0KICAgICAgICAgICAgU3lzdGVtLmluLnJlYWQoKTsNCiAgICAgICAgICAgIHNlcnZlci5zdG9wKCk7DQogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIkFsbCBkb25lLCBoYXZlIGEgZ29vZCBkYXkhIik7DQogICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7DQogICAgICAgICAgICBlLnByaW50U3RhY2tUcmFjZSgpOw0KICAgICAgICAgICAgU3lzdGVtLmV4aXQoMSk7DQogICAgICAgIH0NCiAgICB9DQogICAgQFJvbGVzQWxsb3dlZCh7Im9yZy5vbmFwLmFhZi5teWFwcC5teVBlcm18bXlJbnN0YW5jZXxteUFjdGlvbiJ9KQ0KICAgIHB1YmxpYyBzdGF0aWMgY2xhc3MgTXlTZXJ2bGV0IGltcGxlbWVudHMgU2VydmxldCB7DQogICAgICAgIHByaXZhdGUgU2VydmxldENvbmZpZyBzZXJ2bGV0Q29uZmlnOw0KICAgICANCiAgICAgICAgcHVibGljIHZvaWQgaW5pdChTZXJ2bGV0Q29uZmlnIGNvbmZpZykgdGhyb3dzIFNlcnZsZXRFeGNlcHRpb24gew0KICAgICAgICAgICAgc2VydmxldENvbmZpZyA9IGNvbmZpZzsNCiAgICAgICAgfQ0KICAgICANCiAgICAgICAgcHVibGljIFNlcnZsZXRDb25maWcgZ2V0U2VydmxldENvbmZpZygpIHsNCiAgICAgICAgICAgIHJldHVybiBzZXJ2bGV0Q29uZmlnOw0KICAgICAgICB9DQogICAgIA0KICAgICAgICBwdWJsaWMgdm9pZCBzZXJ2aWNlKFNlcnZsZXRSZXF1ZXN0IHJlcSwgU2VydmxldFJlc3BvbnNlIHJlcykgdGhyb3dzIFNlcnZsZXRFeGNlcHRpb24sIElPRXhjZXB0aW9uIHsNCiAgICAgICAgICAgIEh0dHBTZXJ2bGV0UmVxdWVzdCByZXF1ZXN0Ow0KICAgICAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgICAgICByZXF1ZXN0ID0gKEh0dHBTZXJ2bGV0UmVxdWVzdClyZXE7DQogICAgICAgICAgICB9IGNhdGNoIChDbGFzc0Nhc3RFeGNlcHRpb24gZSkgew0KICAgICAgICAgICAgICAgIHRocm93IG5ldyBTZXJ2bGV0RXhjZXB0aW9uKCJPbmx5IHNlcnZpbmcgSFRUUCB0b2RheSIsZSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICAgDQogICAgICAgICAgICByZXMuZ2V0T3V0cHV0U3RyZWFtKCkucHJpbnQoIjxodG1sPjxoZWFkZXI+PHRpdGxlPkNTUCBTZXJ2bGV0IFRlc3Q8L3RpdGxlPjwvaGVhZGVyPjxib2R5PjxoMT5Zb3UncmUgZ29vZCB0byBnbyE8L2gxPjxwcmU+IiArDQogICAgICAgICAgICAgICAgICAgIHJlcXVlc3QuZ2V0VXNlclByaW5jaXBhbCgpKTsNCiAgICAgICAgICAgICANCiAgICAgICAgICAgIFN0cmluZyBwZXJtID0gcmVxdWVzdC5nZXRQYXJhbWV0ZXIoIlBFUk0iKTsNCiAgICAgICAgICAgIGlmKHBlcm0hPW51bGwpDQogICAgICAgICAgICAgICAgaWYocmVxdWVzdC5pc1VzZXJJblJvbGUocGVybSkpIHsNCiAgICAgICAgICAgICAgICAgICAgaWYocGVybS5pbmRleE9mKCd8Jyk8MCkgDQogICAgICAgICAgICAgICAgICAgICAgICByZXMuZ2V0T3V0cHV0U3RyZWFtKCkucHJpbnQoIlxuQ29uZ3JhdHMhLCBZb3UgYXJlIGluIFJvbGUgIiArIHBlcm0pOw0KICAgICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICAgICAgICAgIHJlcy5nZXRPdXRwdXRTdHJlYW0oKS5wcmludCgiXG5Db25ncmF0cyEsIFlvdSBoYXZlIFBlcm1pc3Npb24gIiArIHBlcm0pOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgIGlmKHBlcm0uaW5kZXhPZignfCcpPDApIA0KICAgICAgICAgICAgICAgICAgICAgICAgcmVzLmdldE91dHB1dFN0cmVhbSgpLnByaW50KCJcblNvcnJ5LCB5b3UgYXJlIE5PVCBpbiBSb2xlICIgKyBwZXJtKTsNCiAgICAgICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAgICAgICByZXMuZ2V0T3V0cHV0U3RyZWFtKCkucHJpbnQoIlxuU29ycnksIHlvdSBkbyBOT1QgaGF2ZSBQZXJtaXNzaW9uICIgKyBwZXJtKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgDQogICAgICAgICAgICByZXMuZ2V0T3V0cHV0U3RyZWFtKCkucHJpbnQoIjwvcHJlPjwvYm9keT48L2h0bWw+Iik7DQogICAgICAgICAgICAgDQogICAgICAgIH0NCiAgICAgDQogICAgICAgIHB1YmxpYyBTdHJpbmcgZ2V0U2VydmxldEluZm8oKSB7DQogICAgICAgICAgICByZXR1cm4gIk15U2VydmxldCI7DQogICAgICAgIH0NCiAgICAgDQogICAgICAgIHB1YmxpYyB2b2lkIGRlc3Ryb3koKSB7DQogICAgICAgIH0NCiAgICB9DQp9DQogDQpKYXZhIERpcmVjdCAoQUFGTHVyKSBNZXRob2QNCj09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KVGhlIEFBRkx1ciBpcyB0aGUgZXhhY3QgY29tcG9uZW50IHVzZWQgd2l0aGluIGFsbCB0aGUgUGx1Z2lucyBtZW50aW9uZWQgYWJvdmUuICBJdCBpcyB3cml0dGVuIHNvIHRoYXQgaXQgY2FuIGJlIGNhbGxlZCBzdGFuZGFsb25lIGFzIHdlbGwsIHNlZSB0aGUgRXhhbXBsZSBhcyBmb2xsb3dzDQpwYWNrYWdlIG9yZy5vbmFwLmFhZi5leGFtcGxlOw0KDQppbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDsNCmltcG9ydCBqYXZhLnV0aWwuTGlzdDsNCmltcG9ydCBqYXZhLnV0aWwuUHJvcGVydGllczsNCg0KaW1wb3J0IG9yZy5vbmFwLmFhZi5jYWRpLkFjY2VzczsNCmltcG9ydCBvcmcub25hcC5hYWYuY2FkaS5QZXJtaXNzaW9uOw0KaW1wb3J0IG9yZy5vbmFwLmFhZi5jYWRpLmFhZi52Ml8wLkFBRkF1dGhuOw0KaW1wb3J0IG9yZy5vbmFwLmFhZi5jYWRpLmFhZi52Ml8wLkFBRkNvbjsNCmltcG9ydCBvcmcub25hcC5hYWYuY2FkaS5hYWYudjJfMC5BQUZMdXJQZXJtOw0KaW1wb3J0IG9yZy5vbmFwLmFhZi5jYWRpLmNvbmZpZy5Db25maWc7DQppbXBvcnQgb3JnLm9uYXAuYWFmLmNhZGkubHVyLmFhZi5BQUZQZXJtaXNzaW9uOw0KaW1wb3J0IG9yZy5vbmFwLmFhZi5jYWRpLmx1ci5hYWYudGVzdC5UZXN0QWNjZXNzOw0KDQpwdWJsaWMgY2xhc3MgRXhhbXBsZVBlcm0yXzAgew0KCXB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZyBhcmdzW10pIHsNCgkJLy8gTm9ybWFsbHksIHRoZXNlIHNob3VsZCBiZSBzZXQgaW4gZW52aXJvbm1lbnQuICBTZXR0aW5nIGhlcmUgZm9yIGNsYXJpdHkNCgkJUHJvcGVydGllcyBwcm9wcyA9IFN5c3RlbS5nZXRQcm9wZXJ0aWVzKCk7DQoJCXByb3BzLnNldFByb3BlcnR5KCJBRlRfTEFUSVRVREUiLCAiMzIuNzgwMTQwIik7DQoJCXByb3BzLnNldFByb3BlcnR5KCJBRlRfTE9OR0lUVURFIiwgIi05Ni44MDA0NTEiKTsNCgkJcHJvcHMuc2V0UHJvcGVydHkoIkFGVF9FTlZJUk9OTUVOVCIsICJBRlRVQVQiKTsNCgkJcHJvcHMuc2V0UHJvcGVydHkoQ29uZmlnLkFBRl9VUkwsDQoJCSJodHRwczovL0RNRTJSRVNPTFZFL3NlcnZpY2U9b3JnLm9uYXAuYWFmLmF1dGh6LkF1dGhvcml6YXRpb25TZXJ2aWNlL3ZlcnNpb249Mi4wL2VudkNvbnRleHQ9VEVTVC9yb3V0ZU9mZmVyPUJBVV9TRSINCgkJCQkpOw0KCQlwcm9wcy5zZXRQcm9wZXJ0eShDb25maWcuQUFGX1VTRVJfRVhQSVJFUyxJbnRlZ2VyLnRvU3RyaW5nKDUqNjAwMDApKTsJLy8gNSBtaW51dGVzIGZvciBmb3VuZCBpdGVtcyB0byBsaXZlIGluIGNhY2hlDQoJCXByb3BzLnNldFByb3BlcnR5KENvbmZpZy5BQUZfSElHSF9DT1VOVCxJbnRlZ2VyLnRvU3RyaW5nKDQwMCkpOwkJLy8gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgaW4gQ2FjaGUpOw0KCQlwcm9wcy5zZXRQcm9wZXJ0eShDb25maWcuQ0FESV9LRVlGSUxFLCJrZXlmaWxlIik7IC8vTm90ZTogQmUgc3VyZSB0byBnZW5lcmF0ZSB3aXRoIGphdmEgLWphciA8Y2FkaV9wYXRoPi9saWIvY2FkaS1jb3JlKi5qYXIga2V5Z2VuIGtleWZpbGUNCi8vCQlwcm9wcy5zZXRQcm9wZXJ0eSgiRE1FMl9FUF9SRUdJU1RSWV9DTEFTUyIsIkRNRTJGUyIpOw0KLy8JCXByb3BzLnNldFByb3BlcnR5KCJBRlRfRE1FMl9FUF9SRUdJU1RSWV9GU19ESVIiLCIuLi8uLi9hdXRoei9kbWUycmVnIik7DQoNCgkJDQoJCS8vIExpbmsgb3IgcmV1c2UgdG8geW91ciBMb2dnaW5nIG1lY2hhbmlzbQ0KCQlBY2Nlc3MgbXlBY2Nlc3MgPSBuZXcgVGVzdEFjY2VzcygpOyAvLyANCgkJDQoJCS8vIA0KCQl0cnkgew0KCQkJQUFGQ29uPD8+IGNvbiA9IG5ldyBBQUZDb25ETUUyKG15QWNjZXNzKTsNCgkJCQ0KCQkJLy8gQUFGTHVyIGhhcyBwb29sIG9mIERNRSBjbGllbnRzIGFzIG5lZWRlZCwgYW5kIENhY2hlcyBDbGllbnQgbG9va3Vwcw0KCQkJQUFGTHVyUGVybSBhYWZMdXIgPSBjb24ubmV3THVyKCk7DQoJCQkvLyBOb3RlOiBJZiB5b3UgbmVlZCBib3RoIEF1dGhuIGFuZCBBdXRoeiBjb25zdHJ1Y3QgdGhlIGZvbGxvd2luZzoNCgkJCUFBRkF1dGhuPD8+IGFhZkF1dGhuID0gY29uLm5ld0F1dGhuKGFhZkx1cik7DQoNCgkJCS8vIERvIG5vdCBzZXQgTWVjaCBJRCB1bnRpbCBhZnRlciB5b3UgY29uc3RydWN0IEFBRkF1dGhuLA0KCQkJLy8gYmVjYXVzZSB3ZSBpbml0aWF0ZSAgIjQwMSIgaW5mbyB0byBkZXRlcm1pbmUgdGhlIFJlYWxtIG9mIA0KCQkJLy8gb2YgdGhlIHNlcnZpY2Ugd2UncmUgYWZ0ZXIuDQoJCQljb24uYmFzaWNBdXRoKCJ4eHh4QGFhZi5hYmMuY29tIiwgIlhYWFhYWCIpOw0KDQoJCQl0cnkgew0KCQkJCQ0KCQkJCS8vIE5vcm1hbGx5LCB5b3Ugb2J0YWluIFByaW5jaXBhbCBmcm9tIEF1dGhlbnRpY2F0aW9uIFN5c3RlbS4NCgkJCQkvLyBGb3IgSjJFRSwgeW91IGNhbiBhc2sgdGhlIEh0dHBTZXJ2bGV0UmVxdWVzdCBmb3IgZ2V0VXNlclByaW5jaXBhbCgpDQoJCQkJLy8gSWYgeW91IHVzZSBDQURJIGFzIEF1dGhlbnRpY2F0b3IsIGl0IHdpbGwgZ2V0IHlvdSB0aGVzZSBQcmluY2lwYWxzIGZyb20NCgkJCQkvLyBDU1Agb3IgQmFzaWNBdXRoIG1lY2hhbmlzbXMuDQoJCQkJU3RyaW5nIGlkID0gInh4eHhAYWFmLmFiYy5jb20iOyAvLyJjbHVzdGVyX2FkbWluQGdyaWRjb3JlLmFiYy5jb20iOw0KDQoJCQkJLy8gSWYgVmFsaWRhdGUgc3VjY2VlZHMsIHlvdSB3aWxsIGdldCBhIE51bGwsIG90aGVyd2lzZSwgeW91IHdpbGwgYSBTdHJpbmcgZm9yIHRoZSByZWFzb24uDQoJCQkJU3RyaW5nIG9rID0gYWFmQXV0aG4udmFsaWRhdGUoaWQsICJYWFhYWFgiKTsNCgkJCQlpZihvayE9bnVsbClTeXN0ZW0ub3V0LnByaW50bG4ob2spOw0KCQkJCQ0KCQkJCW9rID0gYWFmQXV0aG4udmFsaWRhdGUoaWQsICJ3cm9uZ1Bhc3MiKTsNCgkJCQlpZihvayE9bnVsbClTeXN0ZW0ub3V0LnByaW50bG4ob2spOw0KDQoNCgkJCQkvLyBBQUYgU3R5bGUgcGVybWlzc2lvbnMgYXJlIGluIHRoZSBmb3JtDQoJCQkJLy8gVHlwZSwgSW5zdGFuY2UsIEFjdGlvbiANCgkJCQlBQUZQZXJtaXNzaW9uIHBlcm0gPSBuZXcgQUFGUGVybWlzc2lvbigib3JnLm9uYXAuYWFmLmdyaWQuY29yZS5jb2giLCI6ZGV2X2NsdXN0ZXIiLCAiV1JJVEUiKTsNCgkJCQkNCgkJCQkvLyBOb3cgeW91IGNhbiBhc2sgdGhlIExVUiAoTG9jYWwgUmVwcmVzZW50YXRpdmUgb2YgdGhlIFVzZXIgUmVwb3NpdG9yeSBhYm91dCBBdXRob3JpemF0aW9uDQoJCQkJLy8gV2l0aCBDQURJLCBpbiBKMkVFLCB5b3UgY2FuIGNhbGwgaXNVc2VySW5Sb2xlKCJvcmcub25hcC5hYWYubXlncm91cHxteXR5cGV8d3JpdGUiKSBvbiB0aGUgUmVxdWVzdCBPYmplY3QgDQoJCQkJLy8gaW5zdGVhZCBvZiBjcmVhdGluZyB5b3VyIG93biBMVVINCgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIkRvZXMgIiArIGlkICsgIiBoYXZlICIgKyBwZXJtKTsNCgkJCQlpZihhYWZMdXIuZmlzaChpZCwgcGVybSkpIHsNCgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJZZXMsIHlvdSBoYXZlIHBlcm1pc3Npb24iKTsNCgkJCQl9IGVsc2Ugew0KCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIk5vLCB5b3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9uIik7DQoJCQkJfQ0KDQoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJEb2VzIEJvZ3VzIGhhdmUgIiArIHBlcm0pOw0KCQkJCWlmKGFhZkx1ci5maXNoKCJCb2d1cyIsIHBlcm0pKSB7DQoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiWWVzLCB5b3UgaGF2ZSBwZXJtaXNzaW9uIik7DQoJCQkJfSBlbHNlIHsNCgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJObywgeW91IGRvbid0IGhhdmUgcGVybWlzc2lvbiIpOw0KCQkJCX0NCg0KCQkJCS8vIE9yIHlvdSBjYW4gYWxsIGZvciBhbGwgdGhlIFBlcm1pc3Npb25zIGF2YWlsYWJsZQ0KCQkJCUxpc3Q8UGVybWlzc2lvbj4gcGVybXMgPSBuZXcgQXJyYXlMaXN0PFBlcm1pc3Npb24+KCk7DQoJCQkJDQoJCQkJYWFmTHVyLmZpc2hBbGwoaWQscGVybXMpOw0KCQkJCWZvcihQZXJtaXNzaW9uIHBybSA6IHBlcm1zKSB7DQoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbihwcm0uZ2V0S2V5KCkpOw0KCQkJCX0NCgkJCQkNCgkJCQkvLyBJdCBtaWdodCBiZSBoZWxwZnVsIGluIHNvbWUgY2FzZXMgdG8gY2xlYXIgdGhlIFVzZXIncyBpZGVudGl0eSBmcm9tIHRoZSBDYWNoZQ0KCQkJCWFhZkx1ci5yZW1vdmUoaWQpOw0KCQkJfSBmaW5hbGx5IHsNCgkJCQlhYWZMdXIuZGVzdHJveSgpOw0KCQkJfQ0KCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgew0KCQkJZS5wcmludFN0YWNrVHJhY2UoKTsNCgkJfQ0KDQoJfQ0KfQ0KDQpUaGVyZSBhcmUgdHdvIGN1cnJlbnQgQUFGIEx1cnMgd2hpY2ggeW91IGNhbiB1dGlsaXplOg0KlQlPcmcub25hcC5hYWYuY2FkaS5hYWYudjJfMC5BQUZMdXJQZXJtIGlzIHRoZSBkZWZhdWx0LCBhbmQgd2lsbCBmaXNoIGJhc2VkIG9uIHRoZSBUaHJlZS1mb2xkICJQZXJtaXNzaW9uIiBzdGFuZGFyZCBpbiBBQUYNClRvIHJ1biB0aGlzIGNvZGUsIHlvdSB3aWxsIG5lZWQgZnJvbSBhIFNXTSBkZXBsb3ltZW50IChvcmcub25hcC5hYWYuY2FkaTpjYWRpLCB0aGVuIHNvZnQgbGluayB0byBqYXJzIG5lZWRlZCk6DQqVCWNhZGktY29yZS08dmVyc2lvbj4uamFyDQqVCWNhZGktYWFmLTx2ZXJzaW9uPi1mdWxsLmphcg0KICAgb3IgYnkgTWF2ZW4NCjxkZXBlbmRlbmN5Pg0KPGdyb3VwSWQ+b3JnLm9uYXAuYWFmLmNhZGk8L2dyb3VwSWQ+DQo8YXJ0aWZhY3RJZD5jYWRpLWFhZjwvYXJ0aWZhY3RJZD4NCjx2ZXJzaW9uPlRIRV9MQVRFU1RfVkVSU0lPTjwvdmVyc2lvbj4NCjxjbGFzc2lmaWVyPmZ1bGw8L2NsYXNzaWZpZXI+IA0KPC9kZXBlbmRlbmN5Pg0KICAgSWYgeW91IG5lZWQgdGhlIEphdmEgQ2xpZW50IGRlZmluaXRpb25zIG9ubHksIA0KIA0KICAgQWxzbyBuZWVkZWQgYXJlIHRoZSBETUUyIENsaWVudCBsaWJyYXJpZXM6DQqVCWRtZTItPHZlcnNpb24+Lmphcg0KlQlkaXNjb3ZlcnktY2x0LTx2ZXJzaW9uPi5qYXINCg0K