LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDE2IEZ1bmRhY2nzbiBUZWNuYWxpYSBSZXNlYXJjaCAmIElubm92YXRpb24uCiAqCiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuIFRoaXMgcHJvZ3JhbSBhbmQgdGhlIGFjY29tcGFueWluZyBtYXRlcmlhbHMKICogYXJlIG1hZGUgYXZhaWxhYmxlIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgRWNsaXBzZSBQdWJsaWMgTGljZW5zZSB2MS4wCiAqIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uLCBhbmQgaXMgYXZhaWxhYmxlIGF0CiAqIGh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvZXBsLXYxMC5odG1sCiAqCiAqIENvbnRyaWJ1dG9yczoKICogICBIdWFzY2FyIEVzcGlub3phIC0gaW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqICAgQWxlamFuZHJhIFJ17XogLSBpbml0aWFsIEFQSSBhbmQgaW1wbGVtZW50YXRpb24KICogICBJZG95YSBEZWwgUu1vIC0gaW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqICAgTWFyaSBDYXJtZW4gUGFsYWNpb3MgLSBpbml0aWFsIEFQSSBhbmQgaW1wbGVtZW50YXRpb24KICogICBBbmdlbCBM83BleiAtIGluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KLyoqCiAqIEdlbmVyYXRlZCB3aXRoIEFjY2VsZW8KICovCnBhY2thZ2Ugb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuaW1wbDsKCi8vIFN0YXJ0IG9mIHVzZXIgY29kZSBmb3IgaW1wb3J0cwppbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwoKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FT2JqZWN0OwoKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS5hcGkuY29tcG9uZW50LklQcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudDsKCmltcG9ydCBvcmcuZWNsaXBzZS5lbWYuZWVmLnJ1bnRpbWUuYXBpLm5vdGlmeS5JUHJvcGVydGllc0VkaXRpb25FdmVudDsKCmltcG9ydCBvcmcuZWNsaXBzZS5lbWYuZWVmLnJ1bnRpbWUuYXBpLnBhcnRzLklTV1RQcm9wZXJ0aWVzRWRpdGlvblBhcnQ7CgppbXBvcnQgb3JnLmVjbGlwc2UuZW1mLmVlZi5ydW50aW1lLmNvbnRleHQuaW1wbC5FT2JqZWN0UHJvcGVydGllc0VkaXRpb25Db250ZXh0OwoKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS5pbXBsLm5vdGlmeS5Qcm9wZXJ0aWVzRWRpdGlvbkV2ZW50OwoKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS5pbXBsLnBhcnRzLkNvbXBvc2l0ZVByb3BlcnRpZXNFZGl0aW9uUGFydDsKCmltcG9ydCBvcmcuZWNsaXBzZS5lbWYuZWVmLnJ1bnRpbWUucG9saWNpZXMuUHJvcGVydGllc0VkaXRpbmdQb2xpY3k7CgppbXBvcnQgb3JnLmVjbGlwc2UuZW1mLmVlZi5ydW50aW1lLnByb3ZpZGVycy5Qcm9wZXJ0aWVzRWRpdGluZ1Byb3ZpZGVyOwoKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS51aS5wYXJ0cy5QYXJ0Q29tcG9zZXI7CgppbXBvcnQgb3JnLmVjbGlwc2UuZW1mLmVlZi5ydW50aW1lLnVpLnBhcnRzLnNlcXVlbmNlLkJpbmRpbmdDb21wb3NpdGlvblNlcXVlbmNlOwppbXBvcnQgb3JnLmVjbGlwc2UuZW1mLmVlZi5ydW50aW1lLnVpLnBhcnRzLnNlcXVlbmNlLkNvbXBvc2l0aW9uU2VxdWVuY2U7CmltcG9ydCBvcmcuZWNsaXBzZS5lbWYuZWVmLnJ1bnRpbWUudWkucGFydHMuc2VxdWVuY2UuQ29tcG9zaXRpb25TdGVwOwoKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS51aS51dGlscy5FZGl0aW5nVXRpbHM7CgppbXBvcnQgb3JnLmVjbGlwc2UuZW1mLmVlZi5ydW50aW1lLnVpLndpZGdldHMuUmVmZXJlbmNlc1RhYmxlOwoKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS51aS53aWRnZXRzLlJlZmVyZW5jZXNUYWJsZS5SZWZlcmVuY2VzVGFibGVMaXN0ZW5lcjsKCmltcG9ydCBvcmcuZWNsaXBzZS5lbWYuZWVmLnJ1bnRpbWUudWkud2lkZ2V0cy5TV1RVdGlsczsKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS51aS53aWRnZXRzLlRhYkVsZW1lbnRUcmVlU2VsZWN0aW9uRGlhbG9nOwoKaW1wb3J0IG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS51aS53aWRnZXRzLnJlZmVyZW5jZXN0YWJsZS5SZWZlcmVuY2VzVGFibGVDb250ZW50UHJvdmlkZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5lbWYuZWVmLnJ1bnRpbWUudWkud2lkZ2V0cy5yZWZlcmVuY2VzdGFibGUuUmVmZXJlbmNlc1RhYmxlU2V0dGluZ3M7CgppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2Uudmlld2Vycy5JU3RydWN0dXJlZFNlbGVjdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuVmlld2VyRmlsdGVyOwoKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC5TV1Q7CgppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LmV2ZW50cy5Gb2N1c0FkYXB0ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLkZvY3VzRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLktleUFkYXB0ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLktleUV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LmV2ZW50cy5TZWxlY3Rpb25BZGFwdGVyOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LmV2ZW50cy5TZWxlY3Rpb25FdmVudDsKCmltcG9ydCBvcmcuZWNsaXBzZS5zd3QubGF5b3V0LkdyaWREYXRhOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LmxheW91dC5HcmlkTGF5b3V0OwoKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLkNvbXBvc2l0ZTsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLkdyb3VwOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuVGV4dDsKCmltcG9ydCBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydDsKaW1wb3J0IG9yZy5lY2xpcHNlLm9wZW5jZXJ0LnBhbS5wcm9jc3BlYy5wcm9jZXNzLnBhcnRzLlByb2Nlc3NWaWV3c1JlcG9zaXRvcnk7CgppbXBvcnQgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucHJvdmlkZXJzLlByb2Nlc3NNZXNzYWdlczsKCi8vIEVuZCBvZiB1c2VyIGNvZGUKCi8qKgogKiAKICogCiAqLwpwdWJsaWMgY2xhc3MgQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsIGV4dGVuZHMgQ29tcG9zaXRlUHJvcGVydGllc0VkaXRpb25QYXJ0IGltcGxlbWVudHMgSVNXVFByb3BlcnRpZXNFZGl0aW9uUGFydCwgQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQgewoKCXByb3RlY3RlZCBUZXh0IGlkOwoJcHJvdGVjdGVkIFRleHQgbmFtZTsKCXByb3RlY3RlZCBUZXh0IGRlc2NyaXB0aW9uOwoJcHJvdGVjdGVkIFRleHQgc3RhcnRUaW1lOwoJcHJvdGVjdGVkIFRleHQgZW5kVGltZTsKCXByb3RlY3RlZCBSZWZlcmVuY2VzVGFibGUgc3ViQWN0aXZpdHk7Cglwcm90ZWN0ZWQgTGlzdDxWaWV3ZXJGaWx0ZXI+IHN1YkFjdGl2aXR5QnVzaW5lc3NGaWx0ZXJzID0gbmV3IEFycmF5TGlzdDxWaWV3ZXJGaWx0ZXI+KCk7Cglwcm90ZWN0ZWQgTGlzdDxWaWV3ZXJGaWx0ZXI+IHN1YkFjdGl2aXR5RmlsdGVycyA9IG5ldyBBcnJheUxpc3Q8Vmlld2VyRmlsdGVyPigpOwoJcHJvdGVjdGVkIFJlZmVyZW5jZXNUYWJsZSBwcmVjZWRpbmdBY3Rpdml0eTsKCXByb3RlY3RlZCBMaXN0PFZpZXdlckZpbHRlcj4gcHJlY2VkaW5nQWN0aXZpdHlCdXNpbmVzc0ZpbHRlcnMgPSBuZXcgQXJyYXlMaXN0PFZpZXdlckZpbHRlcj4oKTsKCXByb3RlY3RlZCBMaXN0PFZpZXdlckZpbHRlcj4gcHJlY2VkaW5nQWN0aXZpdHlGaWx0ZXJzID0gbmV3IEFycmF5TGlzdDxWaWV3ZXJGaWx0ZXI+KCk7Cglwcm90ZWN0ZWQgUmVmZXJlbmNlc1RhYmxlIG93bmVkUmVsOwoJcHJvdGVjdGVkIExpc3Q8Vmlld2VyRmlsdGVyPiBvd25lZFJlbEJ1c2luZXNzRmlsdGVycyA9IG5ldyBBcnJheUxpc3Q8Vmlld2VyRmlsdGVyPigpOwoJcHJvdGVjdGVkIExpc3Q8Vmlld2VyRmlsdGVyPiBvd25lZFJlbEZpbHRlcnMgPSBuZXcgQXJyYXlMaXN0PFZpZXdlckZpbHRlcj4oKTsKCgoKCS8qKgoJICogRGVmYXVsdCBjb25zdHJ1Y3RvcgoJICogQHBhcmFtIGVkaXRpb25Db21wb25lbnQgdGhlIHtAbGluayBJUHJvcGVydGllc0VkaXRpb25Db21wb25lbnR9IHRoYXQgbWFuYWdlIHRoaXMgcGFydAoJICogCgkgKi8KCXB1YmxpYyBBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwoSVByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50IGVkaXRpb25Db21wb25lbnQpIHsKCQlzdXBlcihlZGl0aW9uQ29tcG9uZW50KTsKCX0KCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5lbWYuZWVmLnJ1bnRpbWUuYXBpLnBhcnRzLklTV1RQcm9wZXJ0aWVzRWRpdGlvblBhcnQjCgkgKiAJCQljcmVhdGVGaWd1cmUob3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuQ29tcG9zaXRlKQoJICogCgkgKi8KCXB1YmxpYyBDb21wb3NpdGUgY3JlYXRlRmlndXJlKGZpbmFsIENvbXBvc2l0ZSBwYXJlbnQpIHsKCQl2aWV3ID0gbmV3IENvbXBvc2l0ZShwYXJlbnQsIFNXVC5OT05FKTsKCQlHcmlkTGF5b3V0IGxheW91dCA9IG5ldyBHcmlkTGF5b3V0KCk7CgkJbGF5b3V0Lm51bUNvbHVtbnMgPSAzOwoJCXZpZXcuc2V0TGF5b3V0KGxheW91dCk7CgkJY3JlYXRlQ29udHJvbHModmlldyk7CgkJcmV0dXJuIHZpZXc7Cgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuZW1mLmVlZi5ydW50aW1lLmFwaS5wYXJ0cy5JU1dUUHJvcGVydGllc0VkaXRpb25QYXJ0IwoJICogCQkJY3JlYXRlQ29udHJvbHMob3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuQ29tcG9zaXRlKQoJICogCgkgKi8KCXB1YmxpYyB2b2lkIGNyZWF0ZUNvbnRyb2xzKENvbXBvc2l0ZSB2aWV3KSB7IAoJCUNvbXBvc2l0aW9uU2VxdWVuY2UgYWN0aXZpdHlTdGVwID0gbmV3IEJpbmRpbmdDb21wb3NpdGlvblNlcXVlbmNlKHByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50KTsKCQlDb21wb3NpdGlvblN0ZXAgcHJvcGVydGllc1N0ZXAgPSBhY3Rpdml0eVN0ZXAuYWRkU3RlcChQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuY2xhc3MpOwoJCXByb3BlcnRpZXNTdGVwLmFkZFN0ZXAoUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLmlkKTsKCQlwcm9wZXJ0aWVzU3RlcC5hZGRTdGVwKFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5uYW1lKTsKCQlwcm9wZXJ0aWVzU3RlcC5hZGRTdGVwKFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5kZXNjcmlwdGlvbik7CgkJcHJvcGVydGllc1N0ZXAuYWRkU3RlcChQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuc3RhcnRUaW1lKTsKCQlwcm9wZXJ0aWVzU3RlcC5hZGRTdGVwKFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5lbmRUaW1lKTsKCQlwcm9wZXJ0aWVzU3RlcC5hZGRTdGVwKFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5zdWJBY3Rpdml0eSk7CgkJcHJvcGVydGllc1N0ZXAuYWRkU3RlcChQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMucHJlY2VkaW5nQWN0aXZpdHkpOwoJCXByb3BlcnRpZXNTdGVwLmFkZFN0ZXAoUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLm93bmVkUmVsKTsKCQkKCQkKCQljb21wb3NlciA9IG5ldyBQYXJ0Q29tcG9zZXIoYWN0aXZpdHlTdGVwKSB7CgoJCQlAT3ZlcnJpZGUKCQkJcHVibGljIENvbXBvc2l0ZSBhZGRUb1BhcnQoQ29tcG9zaXRlIHBhcmVudCwgT2JqZWN0IGtleSkgewoJCQkJaWYgKGtleSA9PSBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuY2xhc3MpIHsKCQkJCQlyZXR1cm4gY3JlYXRlUHJvcGVydGllc0dyb3VwKHBhcmVudCk7CgkJCQl9CgkJCQlpZiAoa2V5ID09IFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5pZCkgewoJCQkJCXJldHVybiBjcmVhdGVJZFRleHQocGFyZW50KTsKCQkJCX0KCQkJCWlmIChrZXkgPT0gUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLm5hbWUpIHsKCQkJCQlyZXR1cm4gY3JlYXRlTmFtZVRleHQocGFyZW50KTsKCQkJCX0KCQkJCWlmIChrZXkgPT0gUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLmRlc2NyaXB0aW9uKSB7CgkJCQkJcmV0dXJuIGNyZWF0ZURlc2NyaXB0aW9uVGV4dChwYXJlbnQpOwoJCQkJfQoJCQkJaWYgKGtleSA9PSBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuc3RhcnRUaW1lKSB7CgkJCQkJcmV0dXJuIGNyZWF0ZVN0YXJ0VGltZVRleHQocGFyZW50KTsKCQkJCX0KCQkJCWlmIChrZXkgPT0gUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLmVuZFRpbWUpIHsKCQkJCQlyZXR1cm4gY3JlYXRlRW5kVGltZVRleHQocGFyZW50KTsKCQkJCX0KCQkJCWlmIChrZXkgPT0gUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnN1YkFjdGl2aXR5KSB7CgkJCQkJcmV0dXJuIGNyZWF0ZVN1YkFjdGl2aXR5QWR2YW5jZWRUYWJsZUNvbXBvc2l0aW9uKHBhcmVudCk7CgkJCQl9CgkJCQlpZiAoa2V5ID09IFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5wcmVjZWRpbmdBY3Rpdml0eSkgewoJCQkJCXJldHVybiBjcmVhdGVQcmVjZWRpbmdBY3Rpdml0eUFkdmFuY2VkUmVmZXJlbmNlc1RhYmxlKHBhcmVudCk7CgkJCQl9CgkJCQlpZiAoa2V5ID09IFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5vd25lZFJlbCkgewoJCQkJCXJldHVybiBjcmVhdGVPd25lZFJlbEFkdmFuY2VkVGFibGVDb21wb3NpdGlvbihwYXJlbnQpOwoJCQkJfQoJCQkJcmV0dXJuIHBhcmVudDsKCQkJfQoJCX07CgkJY29tcG9zZXIuY29tcG9zZSh2aWV3KTsKCX0KCgkvKioKCSAqIAoJICovCglwcm90ZWN0ZWQgQ29tcG9zaXRlIGNyZWF0ZVByb3BlcnRpZXNHcm91cChDb21wb3NpdGUgcGFyZW50KSB7CgkJR3JvdXAgcHJvcGVydGllc0dyb3VwID0gbmV3IEdyb3VwKHBhcmVudCwgU1dULk5PTkUpOwoJCXByb3BlcnRpZXNHcm91cC5zZXRUZXh0KFByb2Nlc3NNZXNzYWdlcy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydF9Qcm9wZXJ0aWVzR3JvdXBMYWJlbCk7CgkJR3JpZERhdGEgcHJvcGVydGllc0dyb3VwRGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwpOwoJCXByb3BlcnRpZXNHcm91cERhdGEuaG9yaXpvbnRhbFNwYW4gPSAzOwoJCXByb3BlcnRpZXNHcm91cC5zZXRMYXlvdXREYXRhKHByb3BlcnRpZXNHcm91cERhdGEpOwoJCUdyaWRMYXlvdXQgcHJvcGVydGllc0dyb3VwTGF5b3V0ID0gbmV3IEdyaWRMYXlvdXQoKTsKCQlwcm9wZXJ0aWVzR3JvdXBMYXlvdXQubnVtQ29sdW1ucyA9IDM7CgkJcHJvcGVydGllc0dyb3VwLnNldExheW91dChwcm9wZXJ0aWVzR3JvdXBMYXlvdXQpOwoJCXJldHVybiBwcm9wZXJ0aWVzR3JvdXA7Cgl9CgoJCglwcm90ZWN0ZWQgQ29tcG9zaXRlIGNyZWF0ZUlkVGV4dChDb21wb3NpdGUgcGFyZW50KSB7CgkJY3JlYXRlRGVzY3JpcHRpb24ocGFyZW50LCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuaWQsIFByb2Nlc3NNZXNzYWdlcy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydF9JZExhYmVsKTsKCQlpZCA9IFNXVFV0aWxzLmNyZWF0ZVNjcm9sbGFibGVUZXh0KHBhcmVudCwgU1dULkJPUkRFUik7CgkJR3JpZERhdGEgaWREYXRhID0gbmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfSE9SSVpPTlRBTCk7CgkJaWQuc2V0TGF5b3V0RGF0YShpZERhdGEpOwoJCWlkLmFkZEZvY3VzTGlzdGVuZXIobmV3IEZvY3VzQWRhcHRlcigpIHsKCgkJCS8qKgoJCQkgKiB7QGluaGVyaXREb2N9CgkJCSAqIAoJCQkgKiBAc2VlIG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuRm9jdXNBZGFwdGVyI2ZvY3VzTG9zdChvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLkZvY3VzRXZlbnQpCgkJCSAqIAoJCQkgKi8KCQkJQE92ZXJyaWRlCgkJCUBTdXBwcmVzc1dhcm5pbmdzKCJzeW50aGV0aWMtYWNjZXNzIikKCQkJcHVibGljIHZvaWQgZm9jdXNMb3N0KEZvY3VzRXZlbnQgZSkgewoJCQkJaWYgKHByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50ICE9IG51bGwpCgkJCQkJcHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZmlyZVByb3BlcnRpZXNDaGFuZ2VkKG5ldyBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50KEFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0SW1wbC50aGlzLCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuaWQsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ09NTUlULCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LlNFVCwgbnVsbCwgaWQuZ2V0VGV4dCgpKSk7CgkJCX0KCgkJfSk7CgkJaWQuYWRkS2V5TGlzdGVuZXIobmV3IEtleUFkYXB0ZXIoKSB7CgoJCQkvKioKCQkJICoge0Bpbmhlcml0RG9jfQoJCQkgKiAKCQkJICogQHNlZSBvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLktleUFkYXB0ZXIja2V5UHJlc3NlZChvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLktleUV2ZW50KQoJCQkgKiAKCQkJICovCgkJCUBPdmVycmlkZQoJCQlAU3VwcHJlc3NXYXJuaW5ncygic3ludGhldGljLWFjY2VzcyIpCgkJCXB1YmxpYyB2b2lkIGtleVByZXNzZWQoS2V5RXZlbnQgZSkgewoJCQkJaWYgKGUuY2hhcmFjdGVyID09IFNXVC5DUikgewoJCQkJCWlmIChwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudCAhPSBudWxsKQoJCQkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5pZCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5DT01NSVQsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuU0VULCBudWxsLCBpZC5nZXRUZXh0KCkpKTsKCQkJCX0KCQkJfQoKCQl9KTsKCQlFZGl0aW5nVXRpbHMuc2V0SUQoaWQsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5pZCk7CgkJRWRpdGluZ1V0aWxzLnNldEVFRnR5cGUoaWQsICJlZWY6OlRleHQiKTsgLy8kTk9OLU5MUy0xJAoJCVNXVFV0aWxzLmNyZWF0ZUhlbHBCdXR0b24ocGFyZW50LCBwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5nZXRIZWxwQ29udGVudChQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuaWQsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuU1dUX0tJTkQpLCBudWxsKTsgLy8kTk9OLU5MUy0xJAoJCS8vIFN0YXJ0IG9mIHVzZXIgY29kZSBmb3IgY3JlYXRlSWRUZXh0CgoJCS8vIEVuZCBvZiB1c2VyIGNvZGUKCQlyZXR1cm4gcGFyZW50OwoJfQoKCQoJcHJvdGVjdGVkIENvbXBvc2l0ZSBjcmVhdGVOYW1lVGV4dChDb21wb3NpdGUgcGFyZW50KSB7CgkJY3JlYXRlRGVzY3JpcHRpb24ocGFyZW50LCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMubmFtZSwgUHJvY2Vzc01lc3NhZ2VzLkFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0X05hbWVMYWJlbCk7CgkJbmFtZSA9IFNXVFV0aWxzLmNyZWF0ZVNjcm9sbGFibGVUZXh0KHBhcmVudCwgU1dULkJPUkRFUik7CgkJR3JpZERhdGEgbmFtZURhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKTsKCQluYW1lLnNldExheW91dERhdGEobmFtZURhdGEpOwoJCW5hbWUuYWRkRm9jdXNMaXN0ZW5lcihuZXcgRm9jdXNBZGFwdGVyKCkgewoKCQkJLyoqCgkJCSAqIHtAaW5oZXJpdERvY30KCQkJICogCgkJCSAqIEBzZWUgb3JnLmVjbGlwc2Uuc3d0LmV2ZW50cy5Gb2N1c0FkYXB0ZXIjZm9jdXNMb3N0KG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuRm9jdXNFdmVudCkKCQkJICogCgkJCSAqLwoJCQlAT3ZlcnJpZGUKCQkJQFN1cHByZXNzV2FybmluZ3MoInN5bnRoZXRpYy1hY2Nlc3MiKQoJCQlwdWJsaWMgdm9pZCBmb2N1c0xvc3QoRm9jdXNFdmVudCBlKSB7CgkJCQlpZiAocHJvcGVydGllc0VkaXRpb25Db21wb25lbnQgIT0gbnVsbCkKCQkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5uYW1lLCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkNPTU1JVCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5TRVQsIG51bGwsIG5hbWUuZ2V0VGV4dCgpKSk7CgkJCX0KCgkJfSk7CgkJbmFtZS5hZGRLZXlMaXN0ZW5lcihuZXcgS2V5QWRhcHRlcigpIHsKCgkJCS8qKgoJCQkgKiB7QGluaGVyaXREb2N9CgkJCSAqIAoJCQkgKiBAc2VlIG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuS2V5QWRhcHRlciNrZXlQcmVzc2VkKG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuS2V5RXZlbnQpCgkJCSAqIAoJCQkgKi8KCQkJQE92ZXJyaWRlCgkJCUBTdXBwcmVzc1dhcm5pbmdzKCJzeW50aGV0aWMtYWNjZXNzIikKCQkJcHVibGljIHZvaWQga2V5UHJlc3NlZChLZXlFdmVudCBlKSB7CgkJCQlpZiAoZS5jaGFyYWN0ZXIgPT0gU1dULkNSKSB7CgkJCQkJaWYgKHByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50ICE9IG51bGwpCgkJCQkJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLm5hbWUsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ09NTUlULCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LlNFVCwgbnVsbCwgbmFtZS5nZXRUZXh0KCkpKTsKCQkJCX0KCQkJfQoKCQl9KTsKCQlFZGl0aW5nVXRpbHMuc2V0SUQobmFtZSwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLm5hbWUpOwoJCUVkaXRpbmdVdGlscy5zZXRFRUZ0eXBlKG5hbWUsICJlZWY6OlRleHQiKTsgLy8kTk9OLU5MUy0xJAoJCVNXVFV0aWxzLmNyZWF0ZUhlbHBCdXR0b24ocGFyZW50LCBwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5nZXRIZWxwQ29udGVudChQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMubmFtZSwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5TV1RfS0lORCksIG51bGwpOyAvLyROT04tTkxTLTEkCgkJLy8gU3RhcnQgb2YgdXNlciBjb2RlIGZvciBjcmVhdGVOYW1lVGV4dAoKCQkvLyBFbmQgb2YgdXNlciBjb2RlCgkJcmV0dXJuIHBhcmVudDsKCX0KCgkKCXByb3RlY3RlZCBDb21wb3NpdGUgY3JlYXRlRGVzY3JpcHRpb25UZXh0KENvbXBvc2l0ZSBwYXJlbnQpIHsKCQljcmVhdGVEZXNjcmlwdGlvbihwYXJlbnQsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5kZXNjcmlwdGlvbiwgUHJvY2Vzc01lc3NhZ2VzLkFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0X0Rlc2NyaXB0aW9uTGFiZWwpOwoJCWRlc2NyaXB0aW9uID0gU1dUVXRpbHMuY3JlYXRlU2Nyb2xsYWJsZVRleHQocGFyZW50LCBTV1QuQk9SREVSKTsKCQlHcmlkRGF0YSBkZXNjcmlwdGlvbkRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKTsKCQlkZXNjcmlwdGlvbi5zZXRMYXlvdXREYXRhKGRlc2NyaXB0aW9uRGF0YSk7CgkJZGVzY3JpcHRpb24uYWRkRm9jdXNMaXN0ZW5lcihuZXcgRm9jdXNBZGFwdGVyKCkgewoKCQkJLyoqCgkJCSAqIHtAaW5oZXJpdERvY30KCQkJICogCgkJCSAqIEBzZWUgb3JnLmVjbGlwc2Uuc3d0LmV2ZW50cy5Gb2N1c0FkYXB0ZXIjZm9jdXNMb3N0KG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuRm9jdXNFdmVudCkKCQkJICogCgkJCSAqLwoJCQlAT3ZlcnJpZGUKCQkJQFN1cHByZXNzV2FybmluZ3MoInN5bnRoZXRpYy1hY2Nlc3MiKQoJCQlwdWJsaWMgdm9pZCBmb2N1c0xvc3QoRm9jdXNFdmVudCBlKSB7CgkJCQlpZiAocHJvcGVydGllc0VkaXRpb25Db21wb25lbnQgIT0gbnVsbCkKCQkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5kZXNjcmlwdGlvbiwgUHJvcGVydGllc0VkaXRpb25FdmVudC5DT01NSVQsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuU0VULCBudWxsLCBkZXNjcmlwdGlvbi5nZXRUZXh0KCkpKTsKCQkJfQoKCQl9KTsKCQlkZXNjcmlwdGlvbi5hZGRLZXlMaXN0ZW5lcihuZXcgS2V5QWRhcHRlcigpIHsKCgkJCS8qKgoJCQkgKiB7QGluaGVyaXREb2N9CgkJCSAqIAoJCQkgKiBAc2VlIG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuS2V5QWRhcHRlciNrZXlQcmVzc2VkKG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuS2V5RXZlbnQpCgkJCSAqIAoJCQkgKi8KCQkJQE92ZXJyaWRlCgkJCUBTdXBwcmVzc1dhcm5pbmdzKCJzeW50aGV0aWMtYWNjZXNzIikKCQkJcHVibGljIHZvaWQga2V5UHJlc3NlZChLZXlFdmVudCBlKSB7CgkJCQlpZiAoZS5jaGFyYWN0ZXIgPT0gU1dULkNSKSB7CgkJCQkJaWYgKHByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50ICE9IG51bGwpCgkJCQkJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLmRlc2NyaXB0aW9uLCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkNPTU1JVCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5TRVQsIG51bGwsIGRlc2NyaXB0aW9uLmdldFRleHQoKSkpOwoJCQkJfQoJCQl9CgoJCX0pOwoJCUVkaXRpbmdVdGlscy5zZXRJRChkZXNjcmlwdGlvbiwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLmRlc2NyaXB0aW9uKTsKCQlFZGl0aW5nVXRpbHMuc2V0RUVGdHlwZShkZXNjcmlwdGlvbiwgImVlZjo6VGV4dCIpOyAvLyROT04tTkxTLTEkCgkJU1dUVXRpbHMuY3JlYXRlSGVscEJ1dHRvbihwYXJlbnQsIHByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmdldEhlbHBDb250ZW50KFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5kZXNjcmlwdGlvbiwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5TV1RfS0lORCksIG51bGwpOyAvLyROT04tTkxTLTEkCgkJLy8gU3RhcnQgb2YgdXNlciBjb2RlIGZvciBjcmVhdGVEZXNjcmlwdGlvblRleHQKCgkJLy8gRW5kIG9mIHVzZXIgY29kZQoJCXJldHVybiBwYXJlbnQ7Cgl9CgoJCglwcm90ZWN0ZWQgQ29tcG9zaXRlIGNyZWF0ZVN0YXJ0VGltZVRleHQoQ29tcG9zaXRlIHBhcmVudCkgewoJCWNyZWF0ZURlc2NyaXB0aW9uKHBhcmVudCwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnN0YXJ0VGltZSwgUHJvY2Vzc01lc3NhZ2VzLkFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0X1N0YXJ0VGltZUxhYmVsKTsKCQlzdGFydFRpbWUgPSBTV1RVdGlscy5jcmVhdGVTY3JvbGxhYmxlVGV4dChwYXJlbnQsIFNXVC5CT1JERVIpOwoJCUdyaWREYXRhIHN0YXJ0VGltZURhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKTsKCQlzdGFydFRpbWUuc2V0TGF5b3V0RGF0YShzdGFydFRpbWVEYXRhKTsKCQlzdGFydFRpbWUuYWRkRm9jdXNMaXN0ZW5lcihuZXcgRm9jdXNBZGFwdGVyKCkgewoKCQkJLyoqCgkJCSAqIHtAaW5oZXJpdERvY30KCQkJICogCgkJCSAqIEBzZWUgb3JnLmVjbGlwc2Uuc3d0LmV2ZW50cy5Gb2N1c0FkYXB0ZXIjZm9jdXNMb3N0KG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuRm9jdXNFdmVudCkKCQkJICogCgkJCSAqLwoJCQlAT3ZlcnJpZGUKCQkJQFN1cHByZXNzV2FybmluZ3MoInN5bnRoZXRpYy1hY2Nlc3MiKQoJCQlwdWJsaWMgdm9pZCBmb2N1c0xvc3QoRm9jdXNFdmVudCBlKSB7CgkJCQlpZiAocHJvcGVydGllc0VkaXRpb25Db21wb25lbnQgIT0gbnVsbCkKCQkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5zdGFydFRpbWUsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ09NTUlULCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LlNFVCwgbnVsbCwgc3RhcnRUaW1lLmdldFRleHQoKSkpOwoJCQl9CgoJCX0pOwoJCXN0YXJ0VGltZS5hZGRLZXlMaXN0ZW5lcihuZXcgS2V5QWRhcHRlcigpIHsKCgkJCS8qKgoJCQkgKiB7QGluaGVyaXREb2N9CgkJCSAqIAoJCQkgKiBAc2VlIG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuS2V5QWRhcHRlciNrZXlQcmVzc2VkKG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuS2V5RXZlbnQpCgkJCSAqIAoJCQkgKi8KCQkJQE92ZXJyaWRlCgkJCUBTdXBwcmVzc1dhcm5pbmdzKCJzeW50aGV0aWMtYWNjZXNzIikKCQkJcHVibGljIHZvaWQga2V5UHJlc3NlZChLZXlFdmVudCBlKSB7CgkJCQlpZiAoZS5jaGFyYWN0ZXIgPT0gU1dULkNSKSB7CgkJCQkJaWYgKHByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50ICE9IG51bGwpCgkJCQkJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnN0YXJ0VGltZSwgUHJvcGVydGllc0VkaXRpb25FdmVudC5DT01NSVQsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuU0VULCBudWxsLCBzdGFydFRpbWUuZ2V0VGV4dCgpKSk7CgkJCQl9CgkJCX0KCgkJfSk7CgkJRWRpdGluZ1V0aWxzLnNldElEKHN0YXJ0VGltZSwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnN0YXJ0VGltZSk7CgkJRWRpdGluZ1V0aWxzLnNldEVFRnR5cGUoc3RhcnRUaW1lLCAiZWVmOjpUZXh0Iik7IC8vJE5PTi1OTFMtMSQKCQlTV1RVdGlscy5jcmVhdGVIZWxwQnV0dG9uKHBhcmVudCwgcHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZ2V0SGVscENvbnRlbnQoUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnN0YXJ0VGltZSwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5TV1RfS0lORCksIG51bGwpOyAvLyROT04tTkxTLTEkCgkJLy8gU3RhcnQgb2YgdXNlciBjb2RlIGZvciBjcmVhdGVTdGFydFRpbWVUZXh0CgoJCS8vIEVuZCBvZiB1c2VyIGNvZGUKCQlyZXR1cm4gcGFyZW50OwoJfQoKCQoJcHJvdGVjdGVkIENvbXBvc2l0ZSBjcmVhdGVFbmRUaW1lVGV4dChDb21wb3NpdGUgcGFyZW50KSB7CgkJY3JlYXRlRGVzY3JpcHRpb24ocGFyZW50LCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuZW5kVGltZSwgUHJvY2Vzc01lc3NhZ2VzLkFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0X0VuZFRpbWVMYWJlbCk7CgkJZW5kVGltZSA9IFNXVFV0aWxzLmNyZWF0ZVNjcm9sbGFibGVUZXh0KHBhcmVudCwgU1dULkJPUkRFUik7CgkJR3JpZERhdGEgZW5kVGltZURhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKTsKCQllbmRUaW1lLnNldExheW91dERhdGEoZW5kVGltZURhdGEpOwoJCWVuZFRpbWUuYWRkRm9jdXNMaXN0ZW5lcihuZXcgRm9jdXNBZGFwdGVyKCkgewoKCQkJLyoqCgkJCSAqIHtAaW5oZXJpdERvY30KCQkJICogCgkJCSAqIEBzZWUgb3JnLmVjbGlwc2Uuc3d0LmV2ZW50cy5Gb2N1c0FkYXB0ZXIjZm9jdXNMb3N0KG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuRm9jdXNFdmVudCkKCQkJICogCgkJCSAqLwoJCQlAT3ZlcnJpZGUKCQkJQFN1cHByZXNzV2FybmluZ3MoInN5bnRoZXRpYy1hY2Nlc3MiKQoJCQlwdWJsaWMgdm9pZCBmb2N1c0xvc3QoRm9jdXNFdmVudCBlKSB7CgkJCQlpZiAocHJvcGVydGllc0VkaXRpb25Db21wb25lbnQgIT0gbnVsbCkKCQkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5lbmRUaW1lLCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkNPTU1JVCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5TRVQsIG51bGwsIGVuZFRpbWUuZ2V0VGV4dCgpKSk7CgkJCX0KCgkJfSk7CgkJZW5kVGltZS5hZGRLZXlMaXN0ZW5lcihuZXcgS2V5QWRhcHRlcigpIHsKCgkJCS8qKgoJCQkgKiB7QGluaGVyaXREb2N9CgkJCSAqIAoJCQkgKiBAc2VlIG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuS2V5QWRhcHRlciNrZXlQcmVzc2VkKG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuS2V5RXZlbnQpCgkJCSAqIAoJCQkgKi8KCQkJQE92ZXJyaWRlCgkJCUBTdXBwcmVzc1dhcm5pbmdzKCJzeW50aGV0aWMtYWNjZXNzIikKCQkJcHVibGljIHZvaWQga2V5UHJlc3NlZChLZXlFdmVudCBlKSB7CgkJCQlpZiAoZS5jaGFyYWN0ZXIgPT0gU1dULkNSKSB7CgkJCQkJaWYgKHByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50ICE9IG51bGwpCgkJCQkJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLmVuZFRpbWUsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ09NTUlULCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LlNFVCwgbnVsbCwgZW5kVGltZS5nZXRUZXh0KCkpKTsKCQkJCX0KCQkJfQoKCQl9KTsKCQlFZGl0aW5nVXRpbHMuc2V0SUQoZW5kVGltZSwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLmVuZFRpbWUpOwoJCUVkaXRpbmdVdGlscy5zZXRFRUZ0eXBlKGVuZFRpbWUsICJlZWY6OlRleHQiKTsgLy8kTk9OLU5MUy0xJAoJCVNXVFV0aWxzLmNyZWF0ZUhlbHBCdXR0b24ocGFyZW50LCBwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5nZXRIZWxwQ29udGVudChQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuZW5kVGltZSwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5TV1RfS0lORCksIG51bGwpOyAvLyROT04tTkxTLTEkCgkJLy8gU3RhcnQgb2YgdXNlciBjb2RlIGZvciBjcmVhdGVFbmRUaW1lVGV4dAoKCQkvLyBFbmQgb2YgdXNlciBjb2RlCgkJcmV0dXJuIHBhcmVudDsKCX0KCgkvKioKCSAqIEBwYXJhbSBjb250YWluZXIKCSAqIAoJICovCglwcm90ZWN0ZWQgQ29tcG9zaXRlIGNyZWF0ZVN1YkFjdGl2aXR5QWR2YW5jZWRUYWJsZUNvbXBvc2l0aW9uKENvbXBvc2l0ZSBwYXJlbnQpIHsKCQl0aGlzLnN1YkFjdGl2aXR5ID0gbmV3IFJlZmVyZW5jZXNUYWJsZShnZXREZXNjcmlwdGlvbihQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuc3ViQWN0aXZpdHksIFByb2Nlc3NNZXNzYWdlcy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydF9TdWJBY3Rpdml0eUxhYmVsKSwgbmV3IFJlZmVyZW5jZXNUYWJsZUxpc3RlbmVyKCkgewoJCQlwdWJsaWMgdm9pZCBoYW5kbGVBZGQoKSB7IAoJCQkJcHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZmlyZVByb3BlcnRpZXNDaGFuZ2VkKG5ldyBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50KEFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0SW1wbC50aGlzLCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuc3ViQWN0aXZpdHksIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ09NTUlULCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkFERCwgbnVsbCwgbnVsbCkpOwoJCQkJc3ViQWN0aXZpdHkucmVmcmVzaCgpOwoJCQl9CgkJCXB1YmxpYyB2b2lkIGhhbmRsZUVkaXQoRU9iamVjdCBlbGVtZW50KSB7CgkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5zdWJBY3Rpdml0eSwgUHJvcGVydGllc0VkaXRpb25FdmVudC5DT01NSVQsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuRURJVCwgbnVsbCwgZWxlbWVudCkpOwoJCQkJc3ViQWN0aXZpdHkucmVmcmVzaCgpOwoJCQl9CgkJCXB1YmxpYyB2b2lkIGhhbmRsZU1vdmUoRU9iamVjdCBlbGVtZW50LCBpbnQgb2xkSW5kZXgsIGludCBuZXdJbmRleCkgeyAKCQkJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnN1YkFjdGl2aXR5LCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkNPTU1JVCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5NT1ZFLCBlbGVtZW50LCBuZXdJbmRleCkpOwoJCQkJc3ViQWN0aXZpdHkucmVmcmVzaCgpOwoJCQl9CgkJCXB1YmxpYyB2b2lkIGhhbmRsZVJlbW92ZShFT2JqZWN0IGVsZW1lbnQpIHsgCgkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5zdWJBY3Rpdml0eSwgUHJvcGVydGllc0VkaXRpb25FdmVudC5DT01NSVQsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuUkVNT1ZFLCBudWxsLCBlbGVtZW50KSk7CgkJCQlzdWJBY3Rpdml0eS5yZWZyZXNoKCk7CgkJCX0KCQkJcHVibGljIHZvaWQgbmF2aWdhdGVUbyhFT2JqZWN0IGVsZW1lbnQpIHsgfQoJCX0pOwoJCWZvciAoVmlld2VyRmlsdGVyIGZpbHRlciA6IHRoaXMuc3ViQWN0aXZpdHlGaWx0ZXJzKSB7CgkJCXRoaXMuc3ViQWN0aXZpdHkuYWRkRmlsdGVyKGZpbHRlcik7CgkJfQoJCXRoaXMuc3ViQWN0aXZpdHkuc2V0SGVscFRleHQocHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZ2V0SGVscENvbnRlbnQoUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnN1YkFjdGl2aXR5LCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LlNXVF9LSU5EKSk7CgkJdGhpcy5zdWJBY3Rpdml0eS5jcmVhdGVDb250cm9scyhwYXJlbnQpOwoJCXRoaXMuc3ViQWN0aXZpdHkuYWRkU2VsZWN0aW9uTGlzdGVuZXIobmV3IFNlbGVjdGlvbkFkYXB0ZXIoKSB7CgkJCQoJCQlwdWJsaWMgdm9pZCB3aWRnZXRTZWxlY3RlZChTZWxlY3Rpb25FdmVudCBlKSB7CgkJCQlpZiAoZS5pdGVtICE9IG51bGwgJiYgZS5pdGVtLmdldERhdGEoKSBpbnN0YW5jZW9mIEVPYmplY3QpIHsKCQkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5zdWJBY3Rpdml0eSwgUHJvcGVydGllc0VkaXRpb25FdmVudC5DSEFOR0UsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuU0VMRUNUSU9OX0NIQU5HRUQsIG51bGwsIGUuaXRlbS5nZXREYXRhKCkpKTsKCQkJCX0KCQkJfQoJCQkKCQl9KTsKCQlHcmlkRGF0YSBzdWJBY3Rpdml0eURhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKTsKCQlzdWJBY3Rpdml0eURhdGEuaG9yaXpvbnRhbFNwYW4gPSAzOwoJCXRoaXMuc3ViQWN0aXZpdHkuc2V0TGF5b3V0RGF0YShzdWJBY3Rpdml0eURhdGEpOwoJCXRoaXMuc3ViQWN0aXZpdHkuc2V0TG93ZXJCb3VuZCgwKTsKCQl0aGlzLnN1YkFjdGl2aXR5LnNldFVwcGVyQm91bmQoLTEpOwoJCXN1YkFjdGl2aXR5LnNldElEKFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5zdWJBY3Rpdml0eSk7CgkJc3ViQWN0aXZpdHkuc2V0RUVGVHlwZSgiZWVmOjpBZHZhbmNlZFRhYmxlQ29tcG9zaXRpb24iKTsgLy8kTk9OLU5MUy0xJAoJCS8vIFN0YXJ0IG9mIHVzZXIgY29kZSBmb3IgY3JlYXRlU3ViQWN0aXZpdHlBZHZhbmNlZFRhYmxlQ29tcG9zaXRpb24KCgkJLy8gRW5kIG9mIHVzZXIgY29kZQoJCXJldHVybiBwYXJlbnQ7Cgl9CgoJLyoqCgkgKiAKCSAqLwoJcHJvdGVjdGVkIENvbXBvc2l0ZSBjcmVhdGVQcmVjZWRpbmdBY3Rpdml0eUFkdmFuY2VkUmVmZXJlbmNlc1RhYmxlKENvbXBvc2l0ZSBwYXJlbnQpIHsKCQlTdHJpbmcgbGFiZWwgPSBnZXREZXNjcmlwdGlvbihQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMucHJlY2VkaW5nQWN0aXZpdHksIFByb2Nlc3NNZXNzYWdlcy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydF9QcmVjZWRpbmdBY3Rpdml0eUxhYmVsKTsJCSAKCQl0aGlzLnByZWNlZGluZ0FjdGl2aXR5ID0gbmV3IFJlZmVyZW5jZXNUYWJsZShsYWJlbCwgbmV3IFJlZmVyZW5jZXNUYWJsZUxpc3RlbmVyKCkgewoJCQlwdWJsaWMgdm9pZCBoYW5kbGVBZGQoKSB7IGFkZFByZWNlZGluZ0FjdGl2aXR5KCk7IH0KCQkJcHVibGljIHZvaWQgaGFuZGxlRWRpdChFT2JqZWN0IGVsZW1lbnQpIHsgZWRpdFByZWNlZGluZ0FjdGl2aXR5KGVsZW1lbnQpOyB9CgkJCXB1YmxpYyB2b2lkIGhhbmRsZU1vdmUoRU9iamVjdCBlbGVtZW50LCBpbnQgb2xkSW5kZXgsIGludCBuZXdJbmRleCkgeyBtb3ZlUHJlY2VkaW5nQWN0aXZpdHkoZWxlbWVudCwgb2xkSW5kZXgsIG5ld0luZGV4KTsgfQoJCQlwdWJsaWMgdm9pZCBoYW5kbGVSZW1vdmUoRU9iamVjdCBlbGVtZW50KSB7IHJlbW92ZUZyb21QcmVjZWRpbmdBY3Rpdml0eShlbGVtZW50KTsgfQoJCQlwdWJsaWMgdm9pZCBuYXZpZ2F0ZVRvKEVPYmplY3QgZWxlbWVudCkgeyB9CgkJfSk7CgkJdGhpcy5wcmVjZWRpbmdBY3Rpdml0eS5zZXRIZWxwVGV4dChwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5nZXRIZWxwQ29udGVudChQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMucHJlY2VkaW5nQWN0aXZpdHksIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuU1dUX0tJTkQpKTsKCQl0aGlzLnByZWNlZGluZ0FjdGl2aXR5LmNyZWF0ZUNvbnRyb2xzKHBhcmVudCk7CgkJdGhpcy5wcmVjZWRpbmdBY3Rpdml0eS5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJCgkJCXB1YmxpYyB2b2lkIHdpZGdldFNlbGVjdGVkKFNlbGVjdGlvbkV2ZW50IGUpIHsKCQkJCWlmIChlLml0ZW0gIT0gbnVsbCAmJiBlLml0ZW0uZ2V0RGF0YSgpIGluc3RhbmNlb2YgRU9iamVjdCkgewoJCQkJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnByZWNlZGluZ0FjdGl2aXR5LCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkNIQU5HRSwgUHJvcGVydGllc0VkaXRpb25FdmVudC5TRUxFQ1RJT05fQ0hBTkdFRCwgbnVsbCwgZS5pdGVtLmdldERhdGEoKSkpOwoJCQkJfQoJCQl9CgkJCQoJCX0pOwoJCUdyaWREYXRhIHByZWNlZGluZ0FjdGl2aXR5RGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwpOwoJCXByZWNlZGluZ0FjdGl2aXR5RGF0YS5ob3Jpem9udGFsU3BhbiA9IDM7CgkJdGhpcy5wcmVjZWRpbmdBY3Rpdml0eS5zZXRMYXlvdXREYXRhKHByZWNlZGluZ0FjdGl2aXR5RGF0YSk7CgkJdGhpcy5wcmVjZWRpbmdBY3Rpdml0eS5kaXNhYmxlTW92ZSgpOwoJCXByZWNlZGluZ0FjdGl2aXR5LnNldElEKFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5wcmVjZWRpbmdBY3Rpdml0eSk7CgkJcHJlY2VkaW5nQWN0aXZpdHkuc2V0RUVGVHlwZSgiZWVmOjpBZHZhbmNlZFJlZmVyZW5jZXNUYWJsZSIpOyAvLyROT04tTkxTLTEkCgkJcmV0dXJuIHBhcmVudDsKCX0KCgkvKioKCSAqIAoJICovCglwcm90ZWN0ZWQgdm9pZCBhZGRQcmVjZWRpbmdBY3Rpdml0eSgpIHsKCQlUYWJFbGVtZW50VHJlZVNlbGVjdGlvbkRpYWxvZyBkaWFsb2cgPSBuZXcgVGFiRWxlbWVudFRyZWVTZWxlY3Rpb25EaWFsb2cocHJlY2VkaW5nQWN0aXZpdHkuZ2V0SW5wdXQoKSwgcHJlY2VkaW5nQWN0aXZpdHlGaWx0ZXJzLCBwcmVjZWRpbmdBY3Rpdml0eUJ1c2luZXNzRmlsdGVycywKCQkicHJlY2VkaW5nQWN0aXZpdHkiLCBwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5nZXRFZGl0aW5nQ29udGV4dCgpLmdldEFkYXB0ZXJGYWN0b3J5KCksIGN1cnJlbnQuZVJlc291cmNlKCkpIHsKCQkJQE92ZXJyaWRlCgkJCXB1YmxpYyB2b2lkIHByb2Nlc3MoSVN0cnVjdHVyZWRTZWxlY3Rpb24gc2VsZWN0aW9uKSB7CgkJCQlmb3IgKEl0ZXJhdG9yPD8+IGl0ZXIgPSBzZWxlY3Rpb24uaXRlcmF0b3IoKTsgaXRlci5oYXNOZXh0KCk7KSB7CgkJCQkJRU9iamVjdCBlbGVtID0gKEVPYmplY3QpIGl0ZXIubmV4dCgpOwoJCQkJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnByZWNlZGluZ0FjdGl2aXR5LAoJCQkJCQlQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkNPTU1JVCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5BREQsIG51bGwsIGVsZW0pKTsKCQkJCX0KCQkJCXByZWNlZGluZ0FjdGl2aXR5LnJlZnJlc2goKTsKCQkJfQoJCX07CgkJZGlhbG9nLm9wZW4oKTsKCX0KCgkvKioKCSAqIAoJICovCglwcm90ZWN0ZWQgdm9pZCBtb3ZlUHJlY2VkaW5nQWN0aXZpdHkoRU9iamVjdCBlbGVtZW50LCBpbnQgb2xkSW5kZXgsIGludCBuZXdJbmRleCkgewoJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLnByZWNlZGluZ0FjdGl2aXR5LCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkNPTU1JVCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5NT1ZFLCBlbGVtZW50LCBuZXdJbmRleCkpOwoJCXByZWNlZGluZ0FjdGl2aXR5LnJlZnJlc2goKTsKCX0KCgkvKioKCSAqIAoJICovCglwcm90ZWN0ZWQgdm9pZCByZW1vdmVGcm9tUHJlY2VkaW5nQWN0aXZpdHkoRU9iamVjdCBlbGVtZW50KSB7CgkJcHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZmlyZVByb3BlcnRpZXNDaGFuZ2VkKG5ldyBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50KEFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0SW1wbC50aGlzLCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMucHJlY2VkaW5nQWN0aXZpdHksIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ09NTUlULCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LlJFTU9WRSwgbnVsbCwgZWxlbWVudCkpOwoJCXByZWNlZGluZ0FjdGl2aXR5LnJlZnJlc2goKTsKCX0KCgkvKioKCSAqIAoJICovCglwcm90ZWN0ZWQgdm9pZCBlZGl0UHJlY2VkaW5nQWN0aXZpdHkoRU9iamVjdCBlbGVtZW50KSB7CgkJRU9iamVjdFByb3BlcnRpZXNFZGl0aW9uQ29udGV4dCBjb250ZXh0ID0gbmV3IEVPYmplY3RQcm9wZXJ0aWVzRWRpdGlvbkNvbnRleHQocHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZ2V0RWRpdGluZ0NvbnRleHQoKSwgcHJvcGVydGllc0VkaXRpb25Db21wb25lbnQsIGVsZW1lbnQsIGFkYXB0ZXJGYWN0b3J5KTsKCQlQcm9wZXJ0aWVzRWRpdGluZ1Byb3ZpZGVyIHByb3ZpZGVyID0gKFByb3BlcnRpZXNFZGl0aW5nUHJvdmlkZXIpYWRhcHRlckZhY3RvcnkuYWRhcHQoZWxlbWVudCwgUHJvcGVydGllc0VkaXRpbmdQcm92aWRlci5jbGFzcyk7CgkJaWYgKHByb3ZpZGVyICE9IG51bGwpIHsKCQkJUHJvcGVydGllc0VkaXRpbmdQb2xpY3kgcG9saWN5ID0gcHJvdmlkZXIuZ2V0UG9saWN5KGNvbnRleHQpOwoJCQlpZiAocG9saWN5ICE9IG51bGwpIHsKCQkJCXBvbGljeS5leGVjdXRlKCk7CgkJCQlwcmVjZWRpbmdBY3Rpdml0eS5yZWZyZXNoKCk7CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBAcGFyYW0gY29udGFpbmVyCgkgKiAKCSAqLwoJcHJvdGVjdGVkIENvbXBvc2l0ZSBjcmVhdGVPd25lZFJlbEFkdmFuY2VkVGFibGVDb21wb3NpdGlvbihDb21wb3NpdGUgcGFyZW50KSB7CgkJdGhpcy5vd25lZFJlbCA9IG5ldyBSZWZlcmVuY2VzVGFibGUoZ2V0RGVzY3JpcHRpb24oUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLm93bmVkUmVsLCBQcm9jZXNzTWVzc2FnZXMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRfT3duZWRSZWxMYWJlbCksIG5ldyBSZWZlcmVuY2VzVGFibGVMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgaGFuZGxlQWRkKCkgeyAKCQkJCXByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmZpcmVQcm9wZXJ0aWVzQ2hhbmdlZChuZXcgUHJvcGVydGllc0VkaXRpb25FdmVudChBY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydEltcGwudGhpcywgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5BY3Rpdml0eS5Qcm9wZXJ0aWVzLm93bmVkUmVsLCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkNPTU1JVCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5BREQsIG51bGwsIG51bGwpKTsKCQkJCW93bmVkUmVsLnJlZnJlc2goKTsKCQkJfQoJCQlwdWJsaWMgdm9pZCBoYW5kbGVFZGl0KEVPYmplY3QgZWxlbWVudCkgewoJCQkJcHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZmlyZVByb3BlcnRpZXNDaGFuZ2VkKG5ldyBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50KEFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0SW1wbC50aGlzLCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMub3duZWRSZWwsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ09NTUlULCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LkVESVQsIG51bGwsIGVsZW1lbnQpKTsKCQkJCW93bmVkUmVsLnJlZnJlc2goKTsKCQkJfQoJCQlwdWJsaWMgdm9pZCBoYW5kbGVNb3ZlKEVPYmplY3QgZWxlbWVudCwgaW50IG9sZEluZGV4LCBpbnQgbmV3SW5kZXgpIHsgCgkJCQlwcm9wZXJ0aWVzRWRpdGlvbkNvbXBvbmVudC5maXJlUHJvcGVydGllc0NoYW5nZWQobmV3IFByb3BlcnRpZXNFZGl0aW9uRXZlbnQoQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnRJbXBsLnRoaXMsIFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5vd25lZFJlbCwgUHJvcGVydGllc0VkaXRpb25FdmVudC5DT01NSVQsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuTU9WRSwgZWxlbWVudCwgbmV3SW5kZXgpKTsKCQkJCW93bmVkUmVsLnJlZnJlc2goKTsKCQkJfQoJCQlwdWJsaWMgdm9pZCBoYW5kbGVSZW1vdmUoRU9iamVjdCBlbGVtZW50KSB7IAoJCQkJcHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZmlyZVByb3BlcnRpZXNDaGFuZ2VkKG5ldyBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50KEFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0SW1wbC50aGlzLCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMub3duZWRSZWwsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ09NTUlULCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LlJFTU9WRSwgbnVsbCwgZWxlbWVudCkpOwoJCQkJb3duZWRSZWwucmVmcmVzaCgpOwoJCQl9CgkJCXB1YmxpYyB2b2lkIG5hdmlnYXRlVG8oRU9iamVjdCBlbGVtZW50KSB7IH0KCQl9KTsKCQlmb3IgKFZpZXdlckZpbHRlciBmaWx0ZXIgOiB0aGlzLm93bmVkUmVsRmlsdGVycykgewoJCQl0aGlzLm93bmVkUmVsLmFkZEZpbHRlcihmaWx0ZXIpOwoJCX0KCQl0aGlzLm93bmVkUmVsLnNldEhlbHBUZXh0KHByb3BlcnRpZXNFZGl0aW9uQ29tcG9uZW50LmdldEhlbHBDb250ZW50KFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5vd25lZFJlbCwgUHJvY2Vzc1ZpZXdzUmVwb3NpdG9yeS5TV1RfS0lORCkpOwoJCXRoaXMub3duZWRSZWwuY3JlYXRlQ29udHJvbHMocGFyZW50KTsKCQl0aGlzLm93bmVkUmVsLmFkZFNlbGVjdGlvbkxpc3RlbmVyKG5ldyBTZWxlY3Rpb25BZGFwdGVyKCkgewoJCQkKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJaWYgKGUuaXRlbSAhPSBudWxsICYmIGUuaXRlbS5nZXREYXRhKCkgaW5zdGFuY2VvZiBFT2JqZWN0KSB7CgkJCQkJcHJvcGVydGllc0VkaXRpb25Db21wb25lbnQuZmlyZVByb3BlcnRpZXNDaGFuZ2VkKG5ldyBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50KEFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0SW1wbC50aGlzLCBQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMub3duZWRSZWwsIFByb3BlcnRpZXNFZGl0aW9uRXZlbnQuQ0hBTkdFLCBQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50LlNFTEVDVElPTl9DSEFOR0VELCBudWxsLCBlLml0ZW0uZ2V0RGF0YSgpKSk7CgkJCQl9CgkJCX0KCQkJCgkJfSk7CgkJR3JpZERhdGEgb3duZWRSZWxEYXRhID0gbmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfSE9SSVpPTlRBTCk7CgkJb3duZWRSZWxEYXRhLmhvcml6b250YWxTcGFuID0gMzsKCQl0aGlzLm93bmVkUmVsLnNldExheW91dERhdGEob3duZWRSZWxEYXRhKTsKCQl0aGlzLm93bmVkUmVsLnNldExvd2VyQm91bmQoMCk7CgkJdGhpcy5vd25lZFJlbC5zZXRVcHBlckJvdW5kKC0xKTsKCQlvd25lZFJlbC5zZXRJRChQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMub3duZWRSZWwpOwoJCW93bmVkUmVsLnNldEVFRlR5cGUoImVlZjo6QWR2YW5jZWRUYWJsZUNvbXBvc2l0aW9uIik7IC8vJE5PTi1OTFMtMSQKCQkvLyBTdGFydCBvZiB1c2VyIGNvZGUgZm9yIGNyZWF0ZU93bmVkUmVsQWR2YW5jZWRUYWJsZUNvbXBvc2l0aW9uCgoJCS8vIEVuZCBvZiB1c2VyIGNvZGUKCQlyZXR1cm4gcGFyZW50OwoJfQoKCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5lbWYuZWVmLnJ1bnRpbWUuYXBpLm5vdGlmeS5JUHJvcGVydGllc0VkaXRpb25MaXN0ZW5lciNmaXJlUHJvcGVydGllc0NoYW5nZWQob3JnLmVjbGlwc2UuZW1mLmVlZi5ydW50aW1lLmFwaS5ub3RpZnkuSVByb3BlcnRpZXNFZGl0aW9uRXZlbnQpCgkgKiAKCSAqLwoJcHVibGljIHZvaWQgZmlyZVByb3BlcnRpZXNDaGFuZ2VkKElQcm9wZXJ0aWVzRWRpdGlvbkV2ZW50IGV2ZW50KSB7CgkJLy8gU3RhcnQgb2YgdXNlciBjb2RlIGZvciB0YWIgc3luY2hyb25pemF0aW9uCgkJCgkJLy8gRW5kIG9mIHVzZXIgY29kZQoJfQoKCS8qKgoJICoge0Bpbmhlcml0RG9jfQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLm9wZW5jZXJ0LnBhbS5wcm9jc3BlYy5wcm9jZXNzLnBhcnRzLkFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0I2dldElkKCkKCSAqIAoJICovCglwdWJsaWMgU3RyaW5nIGdldElkKCkgewoJCXJldHVybiBpZC5nZXRUZXh0KCk7Cgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjc2V0SWQoU3RyaW5nIG5ld1ZhbHVlKQoJICogCgkgKi8KCXB1YmxpYyB2b2lkIHNldElkKFN0cmluZyBuZXdWYWx1ZSkgewoJCWlmIChuZXdWYWx1ZSAhPSBudWxsKSB7CgkJCWlkLnNldFRleHQobmV3VmFsdWUpOwoJCX0gZWxzZSB7CgkJCWlkLnNldFRleHQoIiIpOyAvLyROT04tTkxTLTEkCgkJfQoJCWJvb2xlYW4gZWVmRWxlbWVudEVkaXRvclJlYWRPbmx5U3RhdGUgPSBpc1JlYWRPbmx5KFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5pZCk7CgkJaWYgKGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmIGlkLmlzRW5hYmxlZCgpKSB7CgkJCWlkLnNldEVuYWJsZWQoZmFsc2UpOwoJCQlpZC5zZXRUb29sVGlwVGV4dChQcm9jZXNzTWVzc2FnZXMuQWN0aXZpdHlfUmVhZE9ubHkpOwoJCX0gZWxzZSBpZiAoIWVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmICFpZC5pc0VuYWJsZWQoKSkgewoJCQlpZC5zZXRFbmFibGVkKHRydWUpOwoJCX0JCgkJCgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjZ2V0TmFtZSgpCgkgKiAKCSAqLwoJcHVibGljIFN0cmluZyBnZXROYW1lKCkgewoJCXJldHVybiBuYW1lLmdldFRleHQoKTsKCX0KCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydCNzZXROYW1lKFN0cmluZyBuZXdWYWx1ZSkKCSAqIAoJICovCglwdWJsaWMgdm9pZCBzZXROYW1lKFN0cmluZyBuZXdWYWx1ZSkgewoJCWlmIChuZXdWYWx1ZSAhPSBudWxsKSB7CgkJCW5hbWUuc2V0VGV4dChuZXdWYWx1ZSk7CgkJfSBlbHNlIHsKCQkJbmFtZS5zZXRUZXh0KCIiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCQlib29sZWFuIGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlID0gaXNSZWFkT25seShQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMubmFtZSk7CgkJaWYgKGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmIG5hbWUuaXNFbmFibGVkKCkpIHsKCQkJbmFtZS5zZXRFbmFibGVkKGZhbHNlKTsKCQkJbmFtZS5zZXRUb29sVGlwVGV4dChQcm9jZXNzTWVzc2FnZXMuQWN0aXZpdHlfUmVhZE9ubHkpOwoJCX0gZWxzZSBpZiAoIWVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmICFuYW1lLmlzRW5hYmxlZCgpKSB7CgkJCW5hbWUuc2V0RW5hYmxlZCh0cnVlKTsKCQl9CQoJCQoJfQoKCS8qKgoJICoge0Bpbmhlcml0RG9jfQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLm9wZW5jZXJ0LnBhbS5wcm9jc3BlYy5wcm9jZXNzLnBhcnRzLkFjdGl2aXR5UHJvcGVydGllc0VkaXRpb25QYXJ0I2dldERlc2NyaXB0aW9uKCkKCSAqIAoJICovCglwdWJsaWMgU3RyaW5nIGdldERlc2NyaXB0aW9uKCkgewoJCXJldHVybiBkZXNjcmlwdGlvbi5nZXRUZXh0KCk7Cgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjc2V0RGVzY3JpcHRpb24oU3RyaW5nIG5ld1ZhbHVlKQoJICogCgkgKi8KCXB1YmxpYyB2b2lkIHNldERlc2NyaXB0aW9uKFN0cmluZyBuZXdWYWx1ZSkgewoJCWlmIChuZXdWYWx1ZSAhPSBudWxsKSB7CgkJCWRlc2NyaXB0aW9uLnNldFRleHQobmV3VmFsdWUpOwoJCX0gZWxzZSB7CgkJCWRlc2NyaXB0aW9uLnNldFRleHQoIiIpOyAvLyROT04tTkxTLTEkCgkJfQoJCWJvb2xlYW4gZWVmRWxlbWVudEVkaXRvclJlYWRPbmx5U3RhdGUgPSBpc1JlYWRPbmx5KFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5kZXNjcmlwdGlvbik7CgkJaWYgKGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmIGRlc2NyaXB0aW9uLmlzRW5hYmxlZCgpKSB7CgkJCWRlc2NyaXB0aW9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCQlkZXNjcmlwdGlvbi5zZXRUb29sVGlwVGV4dChQcm9jZXNzTWVzc2FnZXMuQWN0aXZpdHlfUmVhZE9ubHkpOwoJCX0gZWxzZSBpZiAoIWVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmICFkZXNjcmlwdGlvbi5pc0VuYWJsZWQoKSkgewoJCQlkZXNjcmlwdGlvbi5zZXRFbmFibGVkKHRydWUpOwoJCX0JCgkJCgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjZ2V0U3RhcnRUaW1lKCkKCSAqIAoJICovCglwdWJsaWMgU3RyaW5nIGdldFN0YXJ0VGltZSgpIHsKCQlyZXR1cm4gc3RhcnRUaW1lLmdldFRleHQoKTsKCX0KCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydCNzZXRTdGFydFRpbWUoU3RyaW5nIG5ld1ZhbHVlKQoJICogCgkgKi8KCXB1YmxpYyB2b2lkIHNldFN0YXJ0VGltZShTdHJpbmcgbmV3VmFsdWUpIHsKCQlpZiAobmV3VmFsdWUgIT0gbnVsbCkgewoJCQlzdGFydFRpbWUuc2V0VGV4dChuZXdWYWx1ZSk7CgkJfSBlbHNlIHsKCQkJc3RhcnRUaW1lLnNldFRleHQoIiIpOyAvLyROT04tTkxTLTEkCgkJfQoJCWJvb2xlYW4gZWVmRWxlbWVudEVkaXRvclJlYWRPbmx5U3RhdGUgPSBpc1JlYWRPbmx5KFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5zdGFydFRpbWUpOwoJCWlmIChlZWZFbGVtZW50RWRpdG9yUmVhZE9ubHlTdGF0ZSAmJiBzdGFydFRpbWUuaXNFbmFibGVkKCkpIHsKCQkJc3RhcnRUaW1lLnNldEVuYWJsZWQoZmFsc2UpOwoJCQlzdGFydFRpbWUuc2V0VG9vbFRpcFRleHQoUHJvY2Vzc01lc3NhZ2VzLkFjdGl2aXR5X1JlYWRPbmx5KTsKCQl9IGVsc2UgaWYgKCFlZWZFbGVtZW50RWRpdG9yUmVhZE9ubHlTdGF0ZSAmJiAhc3RhcnRUaW1lLmlzRW5hYmxlZCgpKSB7CgkJCXN0YXJ0VGltZS5zZXRFbmFibGVkKHRydWUpOwoJCX0JCgkJCgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjZ2V0RW5kVGltZSgpCgkgKiAKCSAqLwoJcHVibGljIFN0cmluZyBnZXRFbmRUaW1lKCkgewoJCXJldHVybiBlbmRUaW1lLmdldFRleHQoKTsKCX0KCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydCNzZXRFbmRUaW1lKFN0cmluZyBuZXdWYWx1ZSkKCSAqIAoJICovCglwdWJsaWMgdm9pZCBzZXRFbmRUaW1lKFN0cmluZyBuZXdWYWx1ZSkgewoJCWlmIChuZXdWYWx1ZSAhPSBudWxsKSB7CgkJCWVuZFRpbWUuc2V0VGV4dChuZXdWYWx1ZSk7CgkJfSBlbHNlIHsKCQkJZW5kVGltZS5zZXRUZXh0KCIiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCQlib29sZWFuIGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlID0gaXNSZWFkT25seShQcm9jZXNzVmlld3NSZXBvc2l0b3J5LkFjdGl2aXR5LlByb3BlcnRpZXMuZW5kVGltZSk7CgkJaWYgKGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmIGVuZFRpbWUuaXNFbmFibGVkKCkpIHsKCQkJZW5kVGltZS5zZXRFbmFibGVkKGZhbHNlKTsKCQkJZW5kVGltZS5zZXRUb29sVGlwVGV4dChQcm9jZXNzTWVzc2FnZXMuQWN0aXZpdHlfUmVhZE9ubHkpOwoJCX0gZWxzZSBpZiAoIWVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmICFlbmRUaW1lLmlzRW5hYmxlZCgpKSB7CgkJCWVuZFRpbWUuc2V0RW5hYmxlZCh0cnVlKTsKCQl9CQoJCQoJfQoKCgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjaW5pdFN1YkFjdGl2aXR5KEVPYmplY3QgY3VycmVudCwgRVJlZmVyZW5jZSBjb250YWluaW5nRmVhdHVyZSwgRVJlZmVyZW5jZSBmZWF0dXJlKQoJICovCglwdWJsaWMgdm9pZCBpbml0U3ViQWN0aXZpdHkoUmVmZXJlbmNlc1RhYmxlU2V0dGluZ3Mgc2V0dGluZ3MpIHsKCQlpZiAoY3VycmVudC5lUmVzb3VyY2UoKSAhPSBudWxsICYmIGN1cnJlbnQuZVJlc291cmNlKCkuZ2V0UmVzb3VyY2VTZXQoKSAhPSBudWxsKQoJCQl0aGlzLnJlc291cmNlU2V0ID0gY3VycmVudC5lUmVzb3VyY2UoKS5nZXRSZXNvdXJjZVNldCgpOwoJCVJlZmVyZW5jZXNUYWJsZUNvbnRlbnRQcm92aWRlciBjb250ZW50UHJvdmlkZXIgPSBuZXcgUmVmZXJlbmNlc1RhYmxlQ29udGVudFByb3ZpZGVyKCk7CgkJc3ViQWN0aXZpdHkuc2V0Q29udGVudFByb3ZpZGVyKGNvbnRlbnRQcm92aWRlcik7CgkJc3ViQWN0aXZpdHkuc2V0SW5wdXQoc2V0dGluZ3MpOwoJCWJvb2xlYW4gZWVmRWxlbWVudEVkaXRvclJlYWRPbmx5U3RhdGUgPSBpc1JlYWRPbmx5KFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5zdWJBY3Rpdml0eSk7CgkJaWYgKGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmIHN1YkFjdGl2aXR5LmlzRW5hYmxlZCgpKSB7CgkJCXN1YkFjdGl2aXR5LnNldEVuYWJsZWQoZmFsc2UpOwoJCQlzdWJBY3Rpdml0eS5zZXRUb29sVGlwVGV4dChQcm9jZXNzTWVzc2FnZXMuQWN0aXZpdHlfUmVhZE9ubHkpOwoJCX0gZWxzZSBpZiAoIWVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmICFzdWJBY3Rpdml0eS5pc0VuYWJsZWQoKSkgewoJCQlzdWJBY3Rpdml0eS5zZXRFbmFibGVkKHRydWUpOwoJCX0JCgkJCgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjdXBkYXRlU3ViQWN0aXZpdHkoKQoJICogCgkgKi8KCXB1YmxpYyB2b2lkIHVwZGF0ZVN1YkFjdGl2aXR5KCkgewoJc3ViQWN0aXZpdHkucmVmcmVzaCgpOwp9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjYWRkRmlsdGVyU3ViQWN0aXZpdHkoVmlld2VyRmlsdGVyIGZpbHRlcikKCSAqIAoJICovCglwdWJsaWMgdm9pZCBhZGRGaWx0ZXJUb1N1YkFjdGl2aXR5KFZpZXdlckZpbHRlciBmaWx0ZXIpIHsKCQlzdWJBY3Rpdml0eUZpbHRlcnMuYWRkKGZpbHRlcik7CgkJaWYgKHRoaXMuc3ViQWN0aXZpdHkgIT0gbnVsbCkgewoJCQl0aGlzLnN1YkFjdGl2aXR5LmFkZEZpbHRlcihmaWx0ZXIpOwoJCX0KCX0KCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydCNhZGRCdXNpbmVzc0ZpbHRlclN1YkFjdGl2aXR5KFZpZXdlckZpbHRlciBmaWx0ZXIpCgkgKiAKCSAqLwoJcHVibGljIHZvaWQgYWRkQnVzaW5lc3NGaWx0ZXJUb1N1YkFjdGl2aXR5KFZpZXdlckZpbHRlciBmaWx0ZXIpIHsKCQlzdWJBY3Rpdml0eUJ1c2luZXNzRmlsdGVycy5hZGQoZmlsdGVyKTsKCX0KCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydCNpc0NvbnRhaW5lZEluU3ViQWN0aXZpdHlUYWJsZShFT2JqZWN0IGVsZW1lbnQpCgkgKiAKCSAqLwoJcHVibGljIGJvb2xlYW4gaXNDb250YWluZWRJblN1YkFjdGl2aXR5VGFibGUoRU9iamVjdCBlbGVtZW50KSB7CgkJcmV0dXJuICgoUmVmZXJlbmNlc1RhYmxlU2V0dGluZ3Mpc3ViQWN0aXZpdHkuZ2V0SW5wdXQoKSkuY29udGFpbnMoZWxlbWVudCk7Cgl9CgoKCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydCNpbml0UHJlY2VkaW5nQWN0aXZpdHkob3JnLmVjbGlwc2UuZW1mLmVlZi5ydW50aW1lLnVpLndpZGdldHMucmVmZXJlbmNlc3RhYmxlLlJlZmVyZW5jZXNUYWJsZVNldHRpbmdzKQoJICovCglwdWJsaWMgdm9pZCBpbml0UHJlY2VkaW5nQWN0aXZpdHkoUmVmZXJlbmNlc1RhYmxlU2V0dGluZ3Mgc2V0dGluZ3MpIHsKCQlpZiAoY3VycmVudC5lUmVzb3VyY2UoKSAhPSBudWxsICYmIGN1cnJlbnQuZVJlc291cmNlKCkuZ2V0UmVzb3VyY2VTZXQoKSAhPSBudWxsKQoJCQl0aGlzLnJlc291cmNlU2V0ID0gY3VycmVudC5lUmVzb3VyY2UoKS5nZXRSZXNvdXJjZVNldCgpOwoJCVJlZmVyZW5jZXNUYWJsZUNvbnRlbnRQcm92aWRlciBjb250ZW50UHJvdmlkZXIgPSBuZXcgUmVmZXJlbmNlc1RhYmxlQ29udGVudFByb3ZpZGVyKCk7CgkJcHJlY2VkaW5nQWN0aXZpdHkuc2V0Q29udGVudFByb3ZpZGVyKGNvbnRlbnRQcm92aWRlcik7CgkJcHJlY2VkaW5nQWN0aXZpdHkuc2V0SW5wdXQoc2V0dGluZ3MpOwoJCWJvb2xlYW4gZWVmRWxlbWVudEVkaXRvclJlYWRPbmx5U3RhdGUgPSBpc1JlYWRPbmx5KFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5wcmVjZWRpbmdBY3Rpdml0eSk7CgkJaWYgKGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmIHByZWNlZGluZ0FjdGl2aXR5LmdldFRhYmxlKCkuaXNFbmFibGVkKCkpIHsKCQkJcHJlY2VkaW5nQWN0aXZpdHkuc2V0RW5hYmxlZChmYWxzZSk7CgkJCXByZWNlZGluZ0FjdGl2aXR5LnNldFRvb2xUaXBUZXh0KFByb2Nlc3NNZXNzYWdlcy5BY3Rpdml0eV9SZWFkT25seSk7CgkJfSBlbHNlIGlmICghZWVmRWxlbWVudEVkaXRvclJlYWRPbmx5U3RhdGUgJiYgIXByZWNlZGluZ0FjdGl2aXR5LmdldFRhYmxlKCkuaXNFbmFibGVkKCkpIHsKCQkJcHJlY2VkaW5nQWN0aXZpdHkuc2V0RW5hYmxlZCh0cnVlKTsKCQl9CgkJCgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjdXBkYXRlUHJlY2VkaW5nQWN0aXZpdHkoKQoJICogCgkgKi8KCXB1YmxpYyB2b2lkIHVwZGF0ZVByZWNlZGluZ0FjdGl2aXR5KCkgewoJcHJlY2VkaW5nQWN0aXZpdHkucmVmcmVzaCgpOwp9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjYWRkRmlsdGVyUHJlY2VkaW5nQWN0aXZpdHkoVmlld2VyRmlsdGVyIGZpbHRlcikKCSAqIAoJICovCglwdWJsaWMgdm9pZCBhZGRGaWx0ZXJUb1ByZWNlZGluZ0FjdGl2aXR5KFZpZXdlckZpbHRlciBmaWx0ZXIpIHsKCQlwcmVjZWRpbmdBY3Rpdml0eUZpbHRlcnMuYWRkKGZpbHRlcik7Cgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjYWRkQnVzaW5lc3NGaWx0ZXJQcmVjZWRpbmdBY3Rpdml0eShWaWV3ZXJGaWx0ZXIgZmlsdGVyKQoJICogCgkgKi8KCXB1YmxpYyB2b2lkIGFkZEJ1c2luZXNzRmlsdGVyVG9QcmVjZWRpbmdBY3Rpdml0eShWaWV3ZXJGaWx0ZXIgZmlsdGVyKSB7CgkJcHJlY2VkaW5nQWN0aXZpdHlCdXNpbmVzc0ZpbHRlcnMuYWRkKGZpbHRlcik7Cgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjaXNDb250YWluZWRJblByZWNlZGluZ0FjdGl2aXR5VGFibGUoRU9iamVjdCBlbGVtZW50KQoJICogCgkgKi8KCXB1YmxpYyBib29sZWFuIGlzQ29udGFpbmVkSW5QcmVjZWRpbmdBY3Rpdml0eVRhYmxlKEVPYmplY3QgZWxlbWVudCkgewoJCXJldHVybiAoKFJlZmVyZW5jZXNUYWJsZVNldHRpbmdzKXByZWNlZGluZ0FjdGl2aXR5LmdldElucHV0KCkpLmNvbnRhaW5zKGVsZW1lbnQpOwoJfQoKCgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjaW5pdE93bmVkUmVsKEVPYmplY3QgY3VycmVudCwgRVJlZmVyZW5jZSBjb250YWluaW5nRmVhdHVyZSwgRVJlZmVyZW5jZSBmZWF0dXJlKQoJICovCglwdWJsaWMgdm9pZCBpbml0T3duZWRSZWwoUmVmZXJlbmNlc1RhYmxlU2V0dGluZ3Mgc2V0dGluZ3MpIHsKCQlpZiAoY3VycmVudC5lUmVzb3VyY2UoKSAhPSBudWxsICYmIGN1cnJlbnQuZVJlc291cmNlKCkuZ2V0UmVzb3VyY2VTZXQoKSAhPSBudWxsKQoJCQl0aGlzLnJlc291cmNlU2V0ID0gY3VycmVudC5lUmVzb3VyY2UoKS5nZXRSZXNvdXJjZVNldCgpOwoJCVJlZmVyZW5jZXNUYWJsZUNvbnRlbnRQcm92aWRlciBjb250ZW50UHJvdmlkZXIgPSBuZXcgUmVmZXJlbmNlc1RhYmxlQ29udGVudFByb3ZpZGVyKCk7CgkJb3duZWRSZWwuc2V0Q29udGVudFByb3ZpZGVyKGNvbnRlbnRQcm92aWRlcik7CgkJb3duZWRSZWwuc2V0SW5wdXQoc2V0dGluZ3MpOwoJCWJvb2xlYW4gZWVmRWxlbWVudEVkaXRvclJlYWRPbmx5U3RhdGUgPSBpc1JlYWRPbmx5KFByb2Nlc3NWaWV3c1JlcG9zaXRvcnkuQWN0aXZpdHkuUHJvcGVydGllcy5vd25lZFJlbCk7CgkJaWYgKGVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmIG93bmVkUmVsLmlzRW5hYmxlZCgpKSB7CgkJCW93bmVkUmVsLnNldEVuYWJsZWQoZmFsc2UpOwoJCQlvd25lZFJlbC5zZXRUb29sVGlwVGV4dChQcm9jZXNzTWVzc2FnZXMuQWN0aXZpdHlfUmVhZE9ubHkpOwoJCX0gZWxzZSBpZiAoIWVlZkVsZW1lbnRFZGl0b3JSZWFkT25seVN0YXRlICYmICFvd25lZFJlbC5pc0VuYWJsZWQoKSkgewoJCQlvd25lZFJlbC5zZXRFbmFibGVkKHRydWUpOwoJCX0JCgkJCgl9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjdXBkYXRlT3duZWRSZWwoKQoJICogCgkgKi8KCXB1YmxpYyB2b2lkIHVwZGF0ZU93bmVkUmVsKCkgewoJb3duZWRSZWwucmVmcmVzaCgpOwp9CgoJLyoqCgkgKiB7QGluaGVyaXREb2N9CgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uub3BlbmNlcnQucGFtLnByb2NzcGVjLnByb2Nlc3MucGFydHMuQWN0aXZpdHlQcm9wZXJ0aWVzRWRpdGlvblBhcnQjYWRkRmlsdGVyT3duZWRSZWwoVmlld2VyRmlsdGVyIGZpbHRlcikKCSAqIAoJICovCglwdWJsaWMgdm9pZCBhZGRGaWx0ZXJUb093bmVkUmVsKFZpZXdlckZpbHRlciBmaWx0ZXIpIHsKCQlvd25lZFJlbEZpbHRlcnMuYWRkKGZpbHRlcik7CgkJaWYgKHRoaXMub3duZWRSZWwgIT0gbnVsbCkgewoJCQl0aGlzLm93bmVkUmVsLmFkZEZpbHRlcihmaWx0ZXIpOwoJCX0KCX0KCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydCNhZGRCdXNpbmVzc0ZpbHRlck93bmVkUmVsKFZpZXdlckZpbHRlciBmaWx0ZXIpCgkgKiAKCSAqLwoJcHVibGljIHZvaWQgYWRkQnVzaW5lc3NGaWx0ZXJUb093bmVkUmVsKFZpZXdlckZpbHRlciBmaWx0ZXIpIHsKCQlvd25lZFJlbEJ1c2luZXNzRmlsdGVycy5hZGQoZmlsdGVyKTsKCX0KCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5vcGVuY2VydC5wYW0ucHJvY3NwZWMucHJvY2Vzcy5wYXJ0cy5BY3Rpdml0eVByb3BlcnRpZXNFZGl0aW9uUGFydCNpc0NvbnRhaW5lZEluT3duZWRSZWxUYWJsZShFT2JqZWN0IGVsZW1lbnQpCgkgKiAKCSAqLwoJcHVibGljIGJvb2xlYW4gaXNDb250YWluZWRJbk93bmVkUmVsVGFibGUoRU9iamVjdCBlbGVtZW50KSB7CgkJcmV0dXJuICgoUmVmZXJlbmNlc1RhYmxlU2V0dGluZ3Mpb3duZWRSZWwuZ2V0SW5wdXQoKSkuY29udGFpbnMoZWxlbWVudCk7Cgl9CgoKCgoKCgkvKioKCSAqIHtAaW5oZXJpdERvY30KCSAqCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmVtZi5lZWYucnVudGltZS5hcGkucGFydHMuSVByb3BlcnRpZXNFZGl0aW9uUGFydCNnZXRUaXRsZSgpCgkgKiAKCSAqLwoJcHVibGljIFN0cmluZyBnZXRUaXRsZSgpIHsKCQlyZXR1cm4gUHJvY2Vzc01lc3NhZ2VzLkFjdGl2aXR5X1BhcnRfVGl0bGU7Cgl9CgoJLy8gU3RhcnQgb2YgdXNlciBjb2RlIGFkZGl0aW9uYWwgbWV0aG9kcwoJCgkvLyBFbmQgb2YgdXNlciBjb2RlCgoKfQo=