LyoNCiAqIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmUgb3IgbW9yZQ0KICogY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZSBkaXN0cmlidXRlZCB3aXRoDQogKiB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuDQogKiBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZSB0byBZb3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMA0KICogKHRoZSAiTGljZW5zZSIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGgNCiAqIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQNCiAqDQogKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wDQogKg0KICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQ0KICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywNCiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLg0KICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZA0KICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuDQogKi8NCnBhY2thZ2Ugb3Blbm5scC50b29scy5wYXJzZV90aGlja2V0LmNvbW11bmljYXRpdmVfYWN0aW9uczsNCg0KaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7DQppbXBvcnQgamF2YS51dGlsLkxpc3Q7DQoNCmltcG9ydCBvcGVubmxwLnRvb2xzLnBhcnNlX3RoaWNrZXQuUGFyc2VUaGlja2V0Ow0KaW1wb3J0IG9wZW5ubHAudG9vbHMucGFyc2VfdGhpY2tldC5Xb3JkV29yZEludGVyU2VudGVuY2VSZWxhdGlvbkFyYzsNCmltcG9ydCBvcGVubmxwLnRvb2xzLnBhcnNlX3RoaWNrZXQubWF0Y2hpbmcuTWF0Y2hlcjsNCmltcG9ydCBvcGVubmxwLnRvb2xzLnNpbWlsYXJpdHkuYXBwcy5IaXRCYXNlOw0KDQppbXBvcnQganVuaXQuZnJhbWV3b3JrLlRlc3RDYXNlOw0KDQpwdWJsaWMgY2xhc3MgQ29tbXVuaWNhdGl2ZUFjdGlvbnNBcmNCdWlsZGVyVGVzdCBleHRlbmRzIFRlc3RDYXNlIHsNCglNYXRjaGVyIG1hdGNoZXIgPSBuZXcgTWF0Y2hlcigpOw0KCQ0KCXB1YmxpYyB2b2lkIHRlc3RDb21tdW5pY2F0aXZlQWN0aW9uc0FyY0J1aWxkZXJUZXN0USgpew0KCQlTdHJpbmcgdGV4dCA9ICJBcyBhIFVTIGNpdGl6ZW4gbGl2aW5nIGFicm9hZCwgSSBhbSBjb25jZXJuZWQgYWJvdXQgdGhlIGhlYWx0aCByZWZvcm0gcmVndWxhdGlvbiBvZiAyMDE0LiAiKw0KCQkJCSJJIGRvIG5vdCB3YW50IHRvIHdhaXQgdGlsbCBJIGFtIHNpY2sgdG8gYnV5IGhlYWx0aCBpbnN1cmFuY2UuICIrDQoJCQkJIllldCBJIGFtIGFmcmFpZCBJIHdpbGwgZW5kIHVwIGJlaW5nIHJlcXVlc3RlZCB0byBwYXkgdGhlIHRheC4gIisNCgkJCQkiQWx0aG91Z2ggSSBsaXZlIGFicm9hZCwgSSBhbSB3b3JyaWVkIGFib3V0IGhhdmluZyB0byBwYXkgYSBmaW5lIGZvciBiZWluZyByZXBvcnRlZCBhcyBub3QgaGF2aW5nIGhlYWx0aCBpbnN1cmFuY2UgY292ZXJhZ2UuICI7DQoJCVBhcnNlVGhpY2tldCBwdCA9IG1hdGNoZXIuYnVpbGRQYXJzZVRoaWNrZXRGcm9tVGV4dFdpdGhSU1QodGV4dCk7DQoJCUxpc3Q8V29yZFdvcmRJbnRlclNlbnRlbmNlUmVsYXRpb25BcmM+IHJlc3VsdHMgPSBuZXcgQXJyYXlMaXN0PFdvcmRXb3JkSW50ZXJTZW50ZW5jZVJlbGF0aW9uQXJjPigpOw0KCQlmb3IoV29yZFdvcmRJbnRlclNlbnRlbmNlUmVsYXRpb25BcmMgYXJjOiBwdC5nZXRBcmNzKCkpew0KCQkJaWYoYXJjLmdldEFyY1R5cGUoKS5nZXRUeXBlKCkuc3RhcnRzV2l0aCgiY2EiKSl7DQoJCQkJcmVzdWx0cy5hZGQoYXJjKTsNCgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oYXJjKTsNCgkJCX0NCgkJfQ0KCQlhc3NlcnRUcnVlKHJlc3VsdHMuc2l6ZSgpPjExKTsNCgkJDQoJfQ0KCXB1YmxpYyB2b2lkIHRlc3RDb21tdW5pY2F0aXZlQWN0aW9uc0FyY0J1aWxkZXJUZXN0QSgpew0KCQlTdHJpbmcgdGV4dCA9CSJQZW9wbGUgYXJlIHdvcnJpZWQgYWJvdXQgcGF5aW5nIGEgZmluZSBmb3Igbm90IGNhcnJ5aW5nIGhlYWx0aCBpbnN1cmFuY2UgY292ZXJhZ2UsIGhhdmluZyBiZWVuIGluZm9ybWVkIGJ5IElSUyBhYm91dCBuZXcgcmVndWxhdGlvbnMuICIrDQoJCQkJIllldCBoYXJkbHkgYW55b25lIGlzIGV4cGVjdGVkIHRvIHBheSB0aGUgdGF4LCB3aGVuIHRoZSBoZWFsdGggcmVmb3JtIGxhdyB0YWtlcyBmdWxsIGVmZmVjdCBpbiAyMDE0LiAiKw0KCQkJCSJUaGUgaW5kaXZpZHVhbCBtYW5kYXRlIGNvbmZpcm1zIHRoYXQgcGVvcGxlIGRvbpJ0IHdhaXQgdW50aWwgdGhleSBhcmUgc2ljayB0byBidXkgaGVhbHRoIGluc3VyYW5jZS4gIisNCgkJCQkiUGVvcGxlIGFyZSBleGVtcHQgZnJvbSBoZWFsdGggaW5zdXJhbmNlIGZpbmUgaWYgdGhleSByZXBvcnQgdGhleSBtYWtlIHRvbyBsaXR0bGUgbW9uZXksIG9yIFVTIGNpdGl6ZW5zIGxpdmluZyBhYnJvYWQuIjsNCgkJUGFyc2VUaGlja2V0IHB0ID0gbWF0Y2hlci5idWlsZFBhcnNlVGhpY2tldEZyb21UZXh0V2l0aFJTVCh0ZXh0KTsNCgkJTGlzdDxXb3JkV29yZEludGVyU2VudGVuY2VSZWxhdGlvbkFyYz4gcmVzdWx0cyA9IG5ldyBBcnJheUxpc3Q8V29yZFdvcmRJbnRlclNlbnRlbmNlUmVsYXRpb25BcmM+KCk7DQoJCWZvcihXb3JkV29yZEludGVyU2VudGVuY2VSZWxhdGlvbkFyYyBhcmM6IHB0LmdldEFyY3MoKSl7DQoJCQlpZihhcmMuZ2V0QXJjVHlwZSgpLmdldFR5cGUoKS5zdGFydHNXaXRoKCJjYSIpKXsNCgkJCQlyZXN1bHRzLmFkZChhcmMpOw0KCQkJCVN5c3RlbS5vdXQucHJpbnRsbihhcmMpOw0KCQkJfQ0KCQl9DQoJCWFzc2VydFRydWUocmVzdWx0cy5zaXplKCk+NSk7DQoJfQ0KCQ0KDQoJDQoNCn0NCg==