LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAxLCAyMDA5IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gaW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqICAgICBKZW5zIEx1a293c2tpL0lubm9vcHJhY3QgLSBpbml0aWFsIHJlbmFtaW5nL3Jlc3RydWN0dXJpbmcKICogICAgIEplc3BlciBTdGVlbiBN+GxsZXIgLSBpbml0aWFsIElEb2N1bWVudEV4dGVuc2lvbjQgc3VwcG9ydCAtICMxMDI4MjIKICogICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VlIGFsc28gIzIzOTExNSkKICogICAgIAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwudGV4dDsKCmltcG9ydCBqYXZhLmlvLlJlYWRlcjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuUGxhdGZvcm07CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUucHJlZmVyZW5jZXMuSVNjb3BlQ29udGV4dDsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5wcmVmZXJlbmNlcy5JbnN0YW5jZVNjb3BlOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5EZWZhdWx0TGluZVRyYWNrZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50RXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZEV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5Eb2N1bWVudFJld3JpdGVTZXNzaW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5Eb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5GaW5kUmVwbGFjZURvY3VtZW50QWRhcHRlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50OwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjM7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudExpc3RlbmVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24zOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uMjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSUxpbmVUcmFja2VyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JTGluZVRyYWNrZXJFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklQb3NpdGlvblVwZGF0ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklSZWdpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklUZXh0U3RvcmU7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklUeXBlZFJlZ2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuUG9zaXRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LlNlcXVlbnRpYWxSZXdyaXRlVGV4dFN0b3JlOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5UeXBlZFJlZ2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5Mb2dnZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwuZG9jdW1lbnQuU3RydWN0dXJlZERvY3VtZW50RmFjdG9yeTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5lbmNvZGluZy5FbmNvZGluZ01lbWVudG87CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwubHRrLnBhcnNlci5SZWdpb25QYXJzZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLkFib3V0VG9CZUNoYW5nZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuSU1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmV2ZW50cy5JU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLk5vQ2hhbmdlRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLlJlZ2lvbkNoYW5nZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuUmVnaW9uc1JlcGxhY2VkRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLlN0cnVjdHVyZWREb2N1bWVudEV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmV2ZW50cy5TdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkRG9jdW1lbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZERvY3VtZW50UmVnaW9uOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLnRleHQuSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbkxpc3Q7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZFBhcnRpdGlvbmluZzsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkVGV4dFJlUGFyc2VyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnRleHQucnVsZXMuU3RydWN0dXJlZFRleHRQYXJ0aXRpb25lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51bmRvLklTdHJ1Y3R1cmVkVGV4dFVuZG9NYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnVuZG8uU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51dGlsLkFzc2VydDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51dGlsLkRlYnVnOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnV0aWwuVXRpbGl0aWVzOwoKCi8qKgogKiBUaGUgc3RhbmRhcmQgaW1wbGVtZW50YXRpb24gb2Ygc3RydWN0dXJlZCBkb2N1bWVudC4KICovCnB1YmxpYyBjbGFzcyBCYXNpY1N0cnVjdHVyZWREb2N1bWVudCBpbXBsZW1lbnRzIElTdHJ1Y3R1cmVkRG9jdW1lbnQsIElEb2N1bWVudEV4dGVuc2lvbiwgSURvY3VtZW50RXh0ZW5zaW9uMywgSURvY3VtZW50RXh0ZW5zaW9uNCwgQ2hhclNlcXVlbmNlLCBJUmVnaW9uQ29tcGFyaWJsZSB7CgoJLyoqCgkgKiBUaGlzIFRocmVhZExvY2FsIGNvbnN0cnVjdCBpcyB1c2VkIHNvIGVhY2ggdGhyZWFkIGNhbiBtYWludGFpbiBpdHMgb25seQoJICogcG9pbnRlciB0byB0aGUgZG91YmxlIGxpbmtlZCBsaXN0IHRoYXQgbWFuYWdlcyB0aGUgZG9jdW1lbnRzIHJlZ2lvbnMuCgkgKiBUaGUgb25seSB0aGluZyB3ZSAiZ2F1cmQiIGZvciBpcyB0aGF0IGEgcHJldmlvdXNseSBjYWNoZWQgcmVnaW9uIGhhcwoJICogYmVlbiBkZWxldGVkLgoJICogCgkgKiBUaGUgb2JqZWN0IHRoYXQgaXMga2VwdCBpbiB0aGUgdGhyZWFkIGxvY2FsJ3MgbWFwLCBpcyBqdXN0IGEgcG9pbnRlciB0bwoJICogYW4gYXJyYXkgcG9zaXRpb24uIFRoYXQncyBiZWNhdXNlIHRoZSBvYmplY3QgdGhlcmUgbmVlZHMgdG8gYmUgImZyZWUiCgkgKiBmcm9tIHJlZmVyZW5jZXMgdG8gb3RoZXIgb2JqZWN0cywgb3IgaXQgd2lsbCBub3QgYmUgZ2FyYmFnZSBjb2xsZWN0ZWQuCgkgKi8KCXByaXZhdGUgY2xhc3MgQ3VycmVudERvY3VtZW50UmVnaW9uQ2FjaGUgewoJCS8vIEknbSBhc3N1bWluZyBmb3Igbm93IHRoZXJlIHdvdWxkIG5ldmVyIGJlIHNvIG1hbnkgdGhyZWFkcyB0aGF0CgkJLy8gdGhpcyBhcnJheUxpc3QgbmVlZHMgdG8gYmUgYm91bmRlZCwgb3IgJ2NsZWFuZWQgdXAnLgoJCS8vIHRoaXMgYXNzdW1wdGlvbiBzaG91bGQgYmUgdGVzdGVkIGluIHByYWN0aWNlIGFuZCBsb25nIHJ1bm5pbmcKCQkvLyBqb2JzIC0tIGZvdW5kIG5vdCB0byBiZSBhIGdvb2QgYXNzdW1wdGlvbi4gU2VlIGJlbG93LgoJCXByaXZhdGUgTGlzdCBjYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5ID0gQ29sbGVjdGlvbnMuc3luY2hyb25pemVkTGlzdChuZXcgQXJyYXlMaXN0KCkpOwoJCXByaXZhdGUgZmluYWwgYm9vbGVhbiBERUJVRyA9IGZhbHNlOwoJCXByaXZhdGUgZmluYWwgaW50IE1BWF9TSVpFID0gNTA7CgoKCQlwcml2YXRlIFRocmVhZExvY2FsIHRocmVhZExvY2FsQ2FjaGVQb3NpdGlvbiA9IG5ldyBUaHJlYWRMb2NhbCgpOwoKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGdldCgpIHsKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24gPSBudWxsOwoJCQlpbnQgcG9zID0gZ2V0VGhyZWFkTG9jYWxQb3NpdGlvbigpOwoJCQl0cnkgewoJCQkJcmVnaW9uID0gKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24pIGNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuZ2V0KHBvcyk7CgkJCX0KCQkJY2F0Y2ggKEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gZSkgewoJCQkJLy8gZXZlbiB0aG91Z2ggdGhlIGNhY2hlZFJlZ2lvblBvc2l0aW9uIGlzIHN5bmNocm9uaXplZCwKCQkJCS8vIHRoYXQganVzdCBtZWFucyBlYWNoIGFjY2VzcyBpcyBzeW5jcm9uaXplZCwgaXRzCgkJCQkvLyBzdGlsbCBwb3NzaWJsZSBmb3IgYW5vdGhlciB0aHJlYWQgdG8gY2F1c2UgaXQgdG8KCQkJCS8vIGJlIGNsZWFyZWQsIGFmdGVyIHRoaXMgdGhyZWFkIGdldHMgaXQgcG9zaXRpb24uCgkJCQkvLyBTbywgaWYgdGhhdCBoYXBwZW5zLCBhbGwgd2UgY2FuIGRvIGlzIHJlc2V0IHRvIGJlZ2lubmluZy4KCQkJCS8vIFRoaXMgc2hvdWxkIGJlIGV4dHJlbWVseSByYXJlIChpbiBvdGhlciB3b3JkcywgcHJvYmFibHkKCQkJCS8vIG5vdCB3b3J0aCB1c2luZyBzeW5jaHJvbml6ZWQgYmxvY2tzCgkJCQkvLyB0byBhY2Nlc3MgY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS4KCQkJCXJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJCXJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCQlpZiAocmVnaW9uID09IG51bGwpIHsKCQkJCXJlZ2lvbiA9IHJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCQllbHNlCgkJCS8vIHJlZ2lvbiBub3QgbnVsbAoJCQlpZiAocmVnaW9uLmlzRGVsZXRlZCgpKSB7CgkJCQlyZWdpb24gPSByZXNldFRvSW5pdGlhbFN0YXRlKCk7CgkJCX0KCQkJcmV0dXJuIHJlZ2lvbjsKCQl9CgoJCXByaXZhdGUgaW50IGdldFRocmVhZExvY2FsUG9zaXRpb24oKSB7CgkJCU9iamVjdCB0aHJlYWRMb2NhbE9iamVjdCA9IHRocmVhZExvY2FsQ2FjaGVQb3NpdGlvbi5nZXQoKTsKCQkJaW50IHBvcyA9IC0xOwoJCQlpZiAodGhyZWFkTG9jYWxPYmplY3QgPT0gbnVsbCkgewoKCQkJCXBvcyA9IHJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJfQoJCQllbHNlIHsKCQkJCXBvcyA9ICgoSW50ZWdlcikgdGhyZWFkTG9jYWxPYmplY3QpLmludFZhbHVlKCk7CgkJCX0KCQkJcmV0dXJuIHBvczsKCQl9CgoJCS8qKgoJCSAqIEByZXR1cm4KCQkgKi8KCQlwcml2YXRlIGludCByZWluaXRUaHJlYWRMb2NhbFBvc2l0aW9uKCkgewoJCQlJbnRlZ2VyIHBvc2l0aW9uOwoJCQlpbnQgcG9zOwoJCQkvLyBUT0RPX2Z1dHVyZTogdGhpbmsgb2YgYSBiZXR0ZXIgc29sdXRpb24gdGhhdCBkb2Vzbid0CgkJCS8vIHJlcXVpcmUgdGhpcyBrbHVkZ2UuIFRoaXMgaXMgZXNwZWNpYWxseSByZXF1aXJlZCBiZWNhdXNlCgkJCS8vIHNvbWUgaW5mcmFzdHVyZSwgc3VjaCBhcyByZWNvbmNpbGVyLCBhY3R1YWxseSBudWxsIG91dAoJCQkvLyB0aGVpciB0aHJlYWQgb2JqZWN0IGFuZCByZWNyZWF0ZSBpdCwgNTAwIG1zZWNzIGxhdGVyCgkJCS8vIChhcHByb3hpbWF0ZWx5KS4KCQkJLy8gTm90ZTogdGhlIGxpa2VseSBzb2x1dGlvbiBpbiBmdXR1cmUgaXMgdG8gY2xlYXIgYWZ0ZXIgZXZlcnkKCQkJLy8gaGVhdnkgdXNlIG9mIGdldENhY2hlZFJlZ2lvbiwgc3VjaCBhcyBpbiBjcmVhdGluZyBub2RlCgkJCS8vIGxpc3RzLCBvciByZXBhcnNpbmcgb3IgcGFydGlvbmluZy4KCQkJaWYgKGNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuc2l6ZSgpID4gTUFYX1NJWkUpIHsKCQkJCWNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuY2xlYXIoKTsKCQkJCWlmIChERUJVRykgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheSBjbGVhcmVkIGF0IHNpemUgIiArIE1BWF9TSVpFKTsgLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJCXBvc2l0aW9uID0gbmV3IEludGVnZXIoY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5zaXplKCkpOwoJCQl0aHJlYWRMb2NhbENhY2hlUG9zaXRpb24uc2V0KHBvc2l0aW9uKTsKCQkJY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5hZGQocG9zaXRpb24uaW50VmFsdWUoKSwgbnVsbCk7CgkJCXBvcyA9IHBvc2l0aW9uLmludFZhbHVlKCk7CgkJCXJldHVybiBwb3M7CgkJfQoKCQlwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVzZXRUb0luaXRpYWxTdGF0ZSgpIHsKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb247CgkJCXJlZ2lvbiA9IGdldEZpcnN0U3RydWN0dXJlZERvY3VtZW50UmVnaW9uKCk7CgkJCXNldChyZWdpb24pOwoJCQlyZXR1cm4gcmVnaW9uOwoJCX0KCgkJLy8gVE9ETzogbWFrZSBwcml2aXRlIGlmIHVzZWQsIGVsc2UgZGVsZXRlCgkJdm9pZCBzZXQoaW50IHBvcywgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24pIHsKCQkJY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5zZXQocG9zLCByZWdpb24pOwoJCX0KCgkJdm9pZCBzZXQoSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24pIHsKCQkJdHJ5IHsKCQkJCWludCBwb3MgPSBnZXRUaHJlYWRMb2NhbFBvc2l0aW9uKCk7CgkJCQljYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5LnNldChwb3MsIHJlZ2lvbik7CgkJCX0KCQkJY2F0Y2ggKEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gZSkgewoJCQkJLy8gZXZlbiB0aG91Z2ggdGhlIGNhY2hlZFJlZ2lvblBvc2l0aW9uIGlzIHN5bmNocm9uaXplZCwKCQkJCS8vIHRoYXQganVzdCBtZWFucyBlYWNoIGFjY2VzcyBpcyBzeW5jcm9uaXplZCwgaXRzCgkJCQkvLyBzdGlsbCBwb3NzaWJsZSBmb3IgYW5vdGhlciB0aHJlYWQgdG8gY2F1c2UgaXQgdG8KCQkJCS8vIGJlIGNsZWFyZWQsIGFmdGVyIHRoaXMgdGhyZWFkIGdldHMgaXQgcG9zaXRpb24uCgkJCQkvLyBTbywgaWYgdGhhdCBoYXBwZW5zLCBhbGwgd2UgY2FuIGRvIGlzIHJlc2V0IHRvIGJlZ2lubmluZy4KCQkJCS8vIFRoaXMgc2hvdWxkIGJlIGV4dHJlbWVseSByYXJlIChpbiBvdGhlciB3b3JkcywgcHJvYmFibHkKCQkJCS8vIG5vdCB3b3J0aCB1c2luZyBzeW5jaHJvbml6ZWQgYmxvY2tzCgkJCQkvLyB0byBhY2Nlc3MgY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS4KCQkJCXJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJCXJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCX0KCX0KCgkvKioKCSAqIFRoaXMgTnVsbERvY3VtZW50RXZlbnQgaXMgdXNlZCB0byBjb21wbGV0ZSB0aGUgImFib3V0VG9DaGFuZ2UiIGFuZAoJICogImNoYW5nZWQiIGN5Y2xlLCB3aGVuIGluIGZhY3QgdGhlIG9yaWdpbmFsIGNoYW5nZSBpcyBubyBsb25nZXIgdmFsaWQuCgkgKiBUaGUgb25seSBrbm93biAodmFsaWQpIGNhc2Ugb2YgdGhpcyBpcyB3aGVuIGEgbW9kZWwgcmUtaW5pdGlhbGl6ZSB0YWtlcwoJICogcGxhY2UsIHdoaWNoIGNhdXNlcyBzZXRUZXh0IHRvIGJlIGNhbGxlZCBpbiB0aGUgbWlkZGxlIG9mIHNvbWUgcHJldmlvdXMKCSAqIGNoYW5nZS4gW1RoaXMgYXJjaGl0ZWN0dXJlIHdpbGwgYmUgaW1wcm92ZWQgaW4gZnV0dXJlXS4KCSAqLwoJcHVibGljIGNsYXNzIE51bGxEb2N1bWVudEV2ZW50IGV4dGVuZHMgRG9jdW1lbnRFdmVudCB7CgkJcHVibGljIE51bGxEb2N1bWVudEV2ZW50KCkgewoJCQl0aGlzKEJhc2ljU3RydWN0dXJlZERvY3VtZW50LnRoaXMsIDAsIDAsICIiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJcHJpdmF0ZSBOdWxsRG9jdW1lbnRFdmVudChJRG9jdW1lbnQgZG9jLCBpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoLCBTdHJpbmcgdGV4dCkgewoJCQlzdXBlcihkb2MsIG9mZnNldCwgbGVuZ3RoLCB0ZXh0KTsKCQl9Cgl9CgoJY2xhc3MgUmVnaXN0ZXJlZFJlcGxhY2UgewoJCS8qKiBUaGUgb3duZXIgb2YgdGhpcyByZXBsYWNlIG9wZXJhdGlvbi4gKi8KCQlJRG9jdW1lbnRMaXN0ZW5lciBmT3duZXI7CgkJLyoqIFRoZSByZXBsYWNlIG9wZXJhdGlvbiAqLwoJCUlEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSBmUmVwbGFjZTsKCgkJLyoqCgkJICogQ3JlYXRlcyBhIG5ldyBidW5kbGUgb2JqZWN0LgoJCSAqIAoJCSAqIEBwYXJhbSBvd25lcgoJCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50IGxpc3RlbmVyIG93bmluZyB0aGUgcmVwbGFjZSBvcGVyYXRpb24KCQkgKiBAcGFyYW0gcmVwbGFjZQoJCSAqICAgICAgICAgICAgdGhlIHJlcGxhY2Ugb3BlcmF0aW9uCgkJICovCgkJUmVnaXN0ZXJlZFJlcGxhY2UoSURvY3VtZW50TGlzdGVuZXIgb3duZXIsIElEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSByZXBsYWNlKSB7CgkJCWZPd25lciA9IG93bmVyOwoJCQlmUmVwbGFjZSA9IHJlcGxhY2U7CgkJfQoJfQoKCS8qKgoJICogdGhlc2UgY29udHJvbCB2YXJpYWJsZSBpc24ndCBtYXJrIGFzICdmaW5hbCcgc2luY2UgdGhlcmUncyBzb21lIHVuaXQKCSAqIHRlc3RzIHRoYXQgbWFuaXB1bGF0ZSBpdC4gRm9yIGZpbmFsIHByb2R1Y3QsIGl0IHNob3VsZCBiZS4KCSAqLwoKCXByaXZhdGUgc3RhdGljIGJvb2xlYW4gVVNFX0xPQ0FMX1RIUkVBRCA9IHRydWU7CgoJLyoqCgkgKiBwdXJlbHkgZm9yIGRlYnVnZ2luZy9wZXJmb3JtYW5jZSBtZWFzdXJlbWVudHMgSW4gcHJhY3RpY2UsIHdvdWxkIGFsd2F5cwoJICogYmUgJ3RydWUnLiAoYW5kIHNob3VsZCBuZXZlciBiZSBjYWxsZWQgYnkgY2FsbGVkIGJ5IGNsaWVudHMpLiBJdHMgbm90CgkgKiAnZmluYWwnIG9yIHByaXZhdGUganVzdCBzbyBpdCBjYW4gYmUgdmFyaWVkIGR1cmluZwoJICogZGVidWdnaW5nL3BlcmZvcm1hbmNlIG1lYXN1cmVtZW50IHJ1bnMuCgkgKiAKCSAqIEBwYXJhbSB1c2VfbG9jYWxfdGhyZWFkCgkgKi8KCXB1YmxpYyBzdGF0aWMgdm9pZCBzZXRVU0VfTE9DQUxfVEhSRUFEKGZpbmFsIGJvb2xlYW4gdXNlX2xvY2FsX3RocmVhZCkgewoJCVVTRV9MT0NBTF9USFJFQUQgPSB1c2VfbG9jYWxfdGhyZWFkOwoJfQoKCXByaXZhdGUgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBjYWNoZWREb2N1bWVudFJlZ2lvbjsKCXByaXZhdGUgRW5jb2RpbmdNZW1lbnRvIGVuY29kaW5nTWVtZW50bzsKCXByaXZhdGUgYm9vbGVhbiBmQWNjZXB0UG9zdE5vdGlmaWNhdGlvblJlcGxhY2VzID0gdHJ1ZTsKCXByaXZhdGUgQ3VycmVudERvY3VtZW50UmVnaW9uQ2FjaGUgZkN1cnJlbnREb2N1bW5ldFJlZ2lvbkNhY2hlOwoJcHJpdmF0ZSBEb2N1bWVudEV2ZW50IGZEb2N1bWVudEV2ZW50OwoJcHJpdmF0ZSBJRG9jdW1lbnRMaXN0ZW5lcltdIGZEb2N1bWVudExpc3RlbmVyczsKCgkvKioKCSAqIFRoZSByZWdpc3RlcmVkIGRvY3VtZW50IHBhcnRpdGlvbmVycy4KCSAqLwoJcHJpdmF0ZSBNYXAgZkRvY3VtZW50UGFydGl0aW9uZXJzOwoJLyoqIFRoZSByZWdpc3RlcmVkIGRvY3VtZW50IHBhcnRpdGlvbmluZyBsaXN0ZW5lcnMgKi8KCXByaXZhdGUgTGlzdCBmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnM7Cglwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZmlyc3REb2N1bWVudFJlZ2lvbjsKCXByaXZhdGUgUmVnaW9uUGFyc2VyIGZQYXJzZXI7Cglwcml2YXRlIEdlbmVyaWNQb3NpdGlvbk1hbmFnZXIgZlBvc2l0aW9uTWFuYWdlcjsKCXByaXZhdGUgTGlzdCBmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXM7Cglwcml2YXRlIElEb2N1bWVudExpc3RlbmVyW10gZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnM7Cglwcml2YXRlIGludCBmUmVlbnRyYW5jZUNvdW50ID0gMDsKCXByaXZhdGUgSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgZlJlUGFyc2VyOwoJcHJpdmF0ZSBpbnQgZlN0b3BwZWRDb3VudCA9IDA7CgoJcHJpdmF0ZSBJVGV4dFN0b3JlIGZTdG9yZTsKCXByaXZhdGUgT2JqZWN0W10gZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnM7Cglwcml2YXRlIE9iamVjdFtdIGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzOwoJcHJpdmF0ZSBPYmplY3RbXSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnM7CgoJcHJpdmF0ZSBMaXN0IGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzOwoKCXByaXZhdGUgSUxpbmVUcmFja2VyIGZUcmFja2VyOwoJcHJpdmF0ZSBJU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlciBmVW5kb01hbmFnZXI7Cglwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gbGFzdERvY3VtZW50UmVnaW9uOwoKCXByaXZhdGUgYnl0ZVtdIGxpc3RlbmVyTG9jayA9IG5ldyBieXRlWzBdOwoJcHJpdmF0ZSBOdWxsRG9jdW1lbnRFdmVudCBOVUxMX0RPQ1VNRU5UX0VWRU5UOwoKCS8qKgoJICogVGhlb3JldGljYWxseSwgYSBkb2N1bWVudCBjYW4gY29udGFpbiBtaXhlZCBsaW5lIGRlbGltaXRlcnMsIGJ1dCB0aGUKCSAqIHVzZXIncyBwcmVmZXJlbmNlIGlzIHVzdWFsbHkgdG8gYmUgaW50ZXJuYWxseSBjb25zaXN0ZW50LgoJICovCglwcml2YXRlIFN0cmluZyBmSW5pdGlhbExpbmVEZWxpbWl0ZXI7Cglwcml2YXRlIGZpbmFsIFN0cmluZyBSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSA9ICJfUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUllfIjsgLy8kTk9OLU5MUy0xJAoJLyoqCgkgKiBDdXJyZW50IHJld3JpdGUgc2Vzc2lvbiwgb3Igbm9uZSBpZiBub3QgcHJlc2VudGx5IHJld3JpdGluZy4KCSAqLwoJcHJpdmF0ZSBEb2N1bWVudFJld3JpdGVTZXNzaW9uIGZBY3RpdmVSZXdyaXRlU2Vzc2lvbjsKCS8qKgoJICogTGFzdCBtb2RpZmljYXRpb24gc3RhbXAsIGF1dG9tYXRpY2FsbHkgdXBkYXRlZCBvbiBjaGFuZ2UuCgkgKi8KCXByaXZhdGUgbG9uZyBmTW9kaWZpY2F0aW9uU3RhbXA7CgkvKioKCSAqIEtlZXBzIHRyYWNrIG9mIG5leHQgbW9kaWZpY2F0aW9uIHN0YW1wLgoJICovCglwcml2YXRlIGxvbmcgZk5leHRNb2RpZmljYXRpb25TdGFtcD0gSURvY3VtZW50RXh0ZW5zaW9uNC5VTktOT1dOX01PRElGSUNBVElPTl9TVEFNUDsKCS8qKgoJICogZGVidWcgdmFyaWFibGUgb25seQoJICogCgkgKiBAcGFyYW0gcGFyc2VyCgkgKi8KCXByaXZhdGUgbG9uZyBzdGFydFN0cmVhbVRpbWU7CgkvKioKCSAqIGRlYnVnIHZhcmlhYmxlIG9ubHkKCSAqIAoJICogQHBhcmFtIHBhcnNlcgoJICovCglwcml2YXRlIGxvbmcgc3RhcnRUaW1lOwoKCXB1YmxpYyBCYXNpY1N0cnVjdHVyZWREb2N1bWVudCgpIHsKCQlzdXBlcigpOwoJCWZDdXJyZW50RG9jdW1uZXRSZWdpb25DYWNoZSA9IG5ldyBDdXJyZW50RG9jdW1lbnRSZWdpb25DYWNoZSgpOwoJCXNldFRleHRTdG9yZShuZXcgU3RydWN0dXJlZERvY3VtZW50VGV4dFN0b3JlKDUwLCAzMDApKTsKCQlzZXRMaW5lVHJhY2tlcihuZXcgRGVmYXVsdExpbmVUcmFja2VyKCkpOwoJCU5VTExfRE9DVU1FTlRfRVZFTlQgPSBuZXcgTnVsbERvY3VtZW50RXZlbnQoKTsKCgkJaW50ZXJuYWxfYWRkUG9zaXRpb25DYXRlZ29yeShSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSk7CgkJaW50ZXJuYWxfYWRkUG9zaXRpb25VcGRhdGVyKG5ldyBEZWxldGVFcXVhbFBvc2l0aW9uVXBkYXRlcihSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSkpOwoKCX0KCgkvKioKCSAqIFRoaXMgaXMgdGhlIHByaW1hcnkgd2F5IHRvIGdldCBhIG5ldyBzdHJ1Y3R1cmVkRG9jdW1lbnQuIEl0cyBiZXN0IHRvCgkgKiB1c2UgdGhlIGZhY3RvcnkgbWV0aG9kcyBpbiBNb2RlbE1hbmdlciB0byBjcmVhdGUgYSBuZXcKCSAqIElTdHJ1Y3R1cmVkRG9jdW1lbnQsIHNpbmNlIGl0IHdpbGwgZ2V0IGFuZCBpbml0aWFsaXplIHRoZSBwYXJzZXIKCSAqIGFjY29yZGluZyB0byB0aGUgZGVzaXJlZCBjb250ZW50IHR5cGUuCgkgKi8KCXB1YmxpYyBCYXNpY1N0cnVjdHVyZWREb2N1bWVudChSZWdpb25QYXJzZXIgcGFyc2VyKSB7CgkJdGhpcygpOwoJCUFzc2VydC5pc05vdE51bGwocGFyc2VyLCAiUHJvZ3JhbSBFcnJvcjogSVN0cnVjdHVyZWREb2N1bWVudCBjYW4gbm90IGJlIGNyZWF0ZWQgd2l0aCBudWxsIHBhcnNlciIpOyAvLyROT04tTkxTLTEkCgkJLy8gZ28gdGhyb3VnaCBzZXR0ZXIgaW4gY2FzZSB0aGVyZSBpcyBzaWRlIGVmZmVjdHMKCQlpbnRlcm5hbF9zZXRQYXJzZXIocGFyc2VyKTsKCX0KCglwcml2YXRlIHZvaWQgX2NsZWFyRG9jdW1lbnRFdmVudCgpIHsKCQkvLyBubyBoYXJkIGFuZCBmYXN0IHJlcXVpcmVtZW50IHRvIG51bGwgb3V0IC4uLiBqdXN0IHNlZW1zIGxpa2UKCQkvLyBhIGdvb2QgaWRlYSwgc2luY2Ugd2UgYXJlIGRvbmUgd2l0aCBpdC4KCQlmRG9jdW1lbnRFdmVudCA9IG51bGw7Cgl9CgoJcHJpdmF0ZSB2b2lkIF9maXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlKE9iamVjdFtdIGxpc3RlbmVycykgewoJCS8vIG1vc3QgRG9jdW1lbnRBYm91dFRvQmVDaGFuZ2VkIGxpc3RlbmVycyBkbyBub3QgYW50aWNpcGF0ZQoJCS8vIERvY3VtZW50RXZlbnQgPT0gbnVsbC4gU28gbWFrZSBzdXJlIGRvY3VtZW50RXZlbnQgaXMgbm90CgkJLy8gbnVsbC4gKHRoaXMgc2hvdWxkIG5ldmVyIGhhcHBlbiwgeWV0IGl0IGRvZXMgc29tZXRpbWVzKQoJCWlmIChmRG9jdW1lbnRFdmVudCA9PSBudWxsKSB7CgkJCWZEb2N1bWVudEV2ZW50ID0gbmV3IE51bGxEb2N1bWVudEV2ZW50KCk7CgkJfQoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQkvLyBOb3RlOiB0aGUgZG9jRXZlbnQgaXMgY3JlYXRlZCBpbiByZXBsYWNlVGV4dCBBUEkKCQkJLy8gZmlyZQoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJKChJRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkuZG9jdW1lbnRBYm91dFRvQmVDaGFuZ2VkKGZEb2N1bWVudEV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIG5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzQWJvdXRUb0NoYW5nZShEb2N1bWVudEV2ZW50IGRvY3VtZW50RXZlbnQpIHsKCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzICE9IG51bGwpIHsKCQkJSXRlcmF0b3IgZSA9IGZEb2N1bWVudFBhcnRpdGlvbmVycy52YWx1ZXMoKS5pdGVyYXRvcigpOwoJCQl3aGlsZSAoZS5oYXNOZXh0KCkpIHsKCQkJCUlEb2N1bWVudFBhcnRpdGlvbmVyIHAgPSAoSURvY3VtZW50UGFydGl0aW9uZXIpIGUubmV4dCgpOwoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQlwLmRvY3VtZW50QWJvdXRUb0JlQ2hhbmdlZChkb2N1bWVudEV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBfZmlyZURvY3VtZW50Q2hhbmdlZChPYmplY3RbXSBsaXN0ZW5lcnMsIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IGV2ZW50KSB7CgoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQkvLyBOT1RFOiBkb2N1bWVudCBldmVudCBpcyBjcmVhdGVkIGluIHJlcGxhY2UgVGV4dCBBUEkgYW5kIHNldFRleHQKCQkJLy8gQVBJCgkJCS8vIG5vdyBmaXJlCgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJLy8gTm90ZXM6IGZEb2N1bWVudEV2ZW50IGNhbiBiZSAic3VkZGVubHkiIG51bGwsIGlmIG9uZSBvZgoJCQkJCS8vIHRoZQoJCQkJCS8vIHByZXZpb3VzIGNoYW5nZXMKCQkJCQkvLyBjYXVzZWQgYSAic2V0VGV4dCIgdG8gYmUgY2FsbGVkLiBUaGUgb25seSBrbm93biBjYXNlIG9mCgkJCQkJLy8gdGhpcwoJCQkJCS8vIGlzIGEgbW9kZWwgcmVzZXQKCQkJCQkvLyBkdWUgdG8gcGFnZSBkaXJlY3RpdmUgY2hhbmdpbmcuIEV2ZW50dWFsbHkgd2Ugc2hvdWxkCgkJCQkJLy8gY2hhbmdlCgkJCQkJLy8gYXJjaGV0ZWN0dXJlIHRvIGhhdmUKCQkJCQkvLyBldmVudCBxdWUgYW5kIGJlIGFibGUgdG8gImNhbmNlbCIgcGVuZGluZyBldmVudHMsIGJ1dAoJCQkJCS8vIGZvcgoJCQkJCS8vIG5vdywgd2UnbGwganVzdCBwYXNzIGEKCQkJCQkvLyBOdWxsRG9jdW1lbnRFdmVudC4gQnkgdGhlIHdheSwgaXQgaXMgaW1wb3J0YW50IHRvIHNlbmQKCQkJCQkvLyBzb21ldGhpbmcsIHNpbmNlIGNsaWVudHMgbWlnaHQKCQkJCQkvLyBoYXZlIGluZGV0ZXJtaW5hbnQgc3RhdGUgZHVlIHRvICJhYm91dFRvQ2hhbmdlIiBiZWluZwoJCQkJCS8vIHNlbnQKCQkJCQkvLyBlYXJsaWVyLgoJCQkJCWlmIChmRG9jdW1lbnRFdmVudCA9PSBudWxsKSB7CgkJCQkJCSgoSURvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLmRvY3VtZW50Q2hhbmdlZChOVUxMX0RPQ1VNRU5UX0VWRU5UKTsKCQkJCQl9CgkJCQkJZWxzZSB7CgkJCQkJCSgoSURvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLmRvY3VtZW50Q2hhbmdlZChmRG9jdW1lbnRFdmVudCk7CgkJCQkJfQoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgbm90aWZ5RG9jdW1lbnRQYXJ0aXRpb25lcnNEb2N1bWVudENoYW5nZWQoRG9jdW1lbnRFdmVudCBkb2N1bWVudEV2ZW50KSB7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyAhPSBudWxsKSB7CgkJCUl0ZXJhdG9yIGUgPSBmRG9jdW1lbnRQYXJ0aXRpb25lcnMudmFsdWVzKCkuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwID0gKElEb2N1bWVudFBhcnRpdGlvbmVyKSBlLm5leHQoKTsKCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJaWYgKHAgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbikgewoJCQkJCQkvLyBJUmVnaW9uIGNoYW5nZWRQYXJ0aW9uID0KCQkJCQkJKChJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbikgcCkuZG9jdW1lbnRDaGFuZ2VkMihkb2N1bWVudEV2ZW50KTsKCQkJCQl9CgkJCQkJZWxzZSB7CgkJCQkJCXAuZG9jdW1lbnRDaGFuZ2VkKGRvY3VtZW50RXZlbnQpOwoJCQkJCX0KCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQl9CgkJfQoJfQoKCglwcml2YXRlIHZvaWQgX2ZpcmVFdmVudChPYmplY3RbXSBsaXN0ZW5lcnMsIE5vQ2hhbmdlRXZlbnQgZXZlbnQpIHsKCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBob2xkTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlzdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCX0KCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCSgoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5ub0NoYW5nZShldmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCWxvbmcgc3RvcFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgSVN0cnVjdHVyZWREb2N1bWVudDo6ZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50LiBUaW1lIHdhcyAiICsgKHN0b3BUaW1lIC0gc3RhcnRUaW1lKSArICIgbXNlY3MgdG8gZmlyZSBOZXdNb2RlbEV2ZW50IHRvIGluc3RhbmNlIG9mICIgKyBob2xkTGlzdGVuZXJzW2ldLmdldENsYXNzKCkpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBfZmlyZUV2ZW50KE9iamVjdFtdIGxpc3RlbmVycywgUmVnaW9uQ2hhbmdlZEV2ZW50IGV2ZW50KSB7CgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkoKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkucmVnaW9uQ2hhbmdlZChldmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCWxvbmcgc3RvcFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgSVN0cnVjdHVyZWREb2N1bWVudDo6ZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50LiBUaW1lIHdhcyAiICsgKHN0b3BUaW1lIC0gc3RhcnRUaW1lKSArICIgbXNlY3MgdG8gZmlyZSBOZXdNb2RlbEV2ZW50IHRvIGluc3RhbmNlIG9mICIgKyBob2xkTGlzdGVuZXJzW2ldLmdldENsYXNzKCkpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBfZmlyZUV2ZW50KE9iamVjdFtdIGxpc3RlbmVycywgUmVnaW9uc1JlcGxhY2VkRXZlbnQgZXZlbnQpIHsKCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBob2xkTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlzdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCX0KCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCSgoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5yZWdpb25zUmVwbGFjZWQoZXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVFdmVudChPYmplY3RbXSBsaXN0ZW5lcnMsIFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50IGV2ZW50KSB7CgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkoKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkubm9kZXNSZXBsYWNlZChldmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCWxvbmcgc3RvcFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgSVN0cnVjdHVyZWREb2N1bWVudDo6ZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50LiBUaW1lIHdhcyAiICsgKHN0b3BUaW1lIC0gc3RhcnRUaW1lKSArICIgbXNlY3MgdG8gZmlyZSBOZXdNb2RlbEV2ZW50IHRvIGluc3RhbmNlIG9mICIgKyBob2xkTGlzdGVuZXJzW2ldLmdldENsYXNzKCkpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBfZmlyZVN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2UoT2JqZWN0W10gbGlzdGVuZXJzKSB7CgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCS8vIE5vdGU6IHRoZSBkb2NFdmVudCBpcyBjcmVhdGVkIGluIHJlcGxhY2VUZXh0IEFQSQoJCQkvLyBmaXJlCgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIG5vdGljZSB0aGUgQWJvdXRUb0JlQ2hhbmdlZEV2ZW50IGlzIGNyZWF0ZWQgZnJvbSB0aGUKCQkJCQkvLyBEb2N1bWVudEV2ZW50LCBzaW5jZSBpdCBpcyAobmVhcmx5KQoJCQkJCS8vIHRoZSBzYW1lIGluZm9ybWF0aW9uLiA/V2hhdCB0byBkbyBhYm91dAoJCQkJCS8vIG9yaWdpbmFsUmVxdWVzdGVyPwoJCQkJCWlmIChmRG9jdW1lbnRFdmVudCA9PSBudWxsKSB7CgkJCQkJCWZEb2N1bWVudEV2ZW50ID0gbmV3IE51bGxEb2N1bWVudEV2ZW50KCk7CgkJCQkJfQoJCQkJCUFib3V0VG9CZUNoYW5nZWRFdmVudCBhYm91dFRvQmVDaGFuZ2VkRXZlbnQgPSBuZXcgQWJvdXRUb0JlQ2hhbmdlZEV2ZW50KHRoaXMsIG51bGwsIGZEb2N1bWVudEV2ZW50LmdldFRleHQoKSwgZkRvY3VtZW50RXZlbnQuZ2V0T2Zmc2V0KCksIGZEb2N1bWVudEV2ZW50LmdldExlbmd0aCgpKTsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJKChJTW9kZWxBYm91dFRvQmVDaGFuZ2VkTGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLm1vZGVsQWJvdXRUb0JlQ2hhbmdlZChhYm91dFRvQmVDaGFuZ2VkRXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcm90ZWN0ZWQgdm9pZCBhY3F1aXJlTG9jaygpIHsKCQkvLyBkbyBub3RoaW5nIGhlcmUgaW4gc3VwZXIgY2xhc3MKCX0KCgkvKioKCSAqIGFkZE1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyIG1ldGhvZCBjb21tZW50LgoJICovCglwdWJsaWMgdm9pZCBhZGREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcihJTW9kZWxBYm91dFRvQmVDaGFuZ2VkTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJLy8gbWFrZSBzdXJlIGxpc3RlbmVyIGlzIG5vdCBhbHJlYWR5IGluIGxpc3RlbmluZwoJCQkvLyAoYW5kIGlmIGl0IGlzLCBwcmludCBhIHdhcm5pbmcgdG8gYWlkIGRlYnVnZ2luZywgaWYgbmVlZGVkKQoJCQlpZiAoIVV0aWxpdGllcy5jb250YWlucyhmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQlpbnQgb2xkU2l6ZSA9IDA7CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCS8vIG5vcm1hbGx5IHdvbid0IGJlIG51bGwsIGJ1dCB3ZSBuZWVkIHRvIGJlIHN1cmUsIGZvcgoJCQkJCS8vIGZpcnN0CgkJCQkJLy8gdGltZSB0aHJvdWdoCgkJCQkJb2xkU2l6ZSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzLmxlbmd0aDsKCQkJCX0KCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSArIDE7CgkJCQlPYmplY3RbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgT2JqZWN0W25ld1NpemVdOwoJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQlTeXN0ZW0uYXJyYXljb3B5KGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzLCAwLCBuZXdMaXN0ZW5lcnMsIDAsIG9sZFNpemUpOwoJCQkJfQoJCQkJLy8gYWRkIGxpc3RlbmVyIHRvIGxhc3QgcG9zaXRpb24KCQkJCW5ld0xpc3RlbmVyc1tuZXdTaXplIC0gMV0gPSBsaXN0ZW5lcjsKCQkJCS8vCgkJCQkvLyBub3cgc3dpdGNoIG5ldyBmb3Igb2xkCgkJCQlmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJCS8vCgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBUaGUgU3RydWN0dXJlZERvY3VtZW50TGlzdG5lcnMgYW5kIE1vZGVsQ2hhZ25lZExpc3RlbmVycyBhcmUgdmVyeQoJICogc2ltaWxhci4gVGhleSBib3RoIHJlY2VpdmUgaWRlbnRpY2FsIGV2ZW50cy4gVGhlIGRpZmZlcmVuY2UgaXMgdGhlCgkgKiB0aW1pbmcuIFRoZSAicHVyZSIgU3RydWN0dXJlZERvY3VtZW50TGlzdG5lcnMgYXJlIG5vdGlmaWVkIGFmdGVyIHRoZQoJICogc3RydWN0dXJlZERvY3VtZW50IGhhcyBiZWVuIGNoYW5nZWQsIGJ1dCBiZWZvcmUgb3RoZXIsIHJlbGF0ZWQgbW9kZWxzCgkgKiBtYXkgaGF2ZSBiZWVuIGNoYW5nZWQgc3VjaCBhcyB0aGUgU3RydWN0dXJhbCBNb2RlbC4gVGhlIFN0cnVjdHVyYWwKCSAqIG1vZGVsIGlzIGluIGZhY3QgaXRzZWxmIGEgInB1cmUiIFN0cnVjdHVyZWREb2N1bWVudExpc3RuZXIuIFRoZQoJICogTW9kZWxDaGFuZ2VkTGlzdGVuZXJzIGNhbiByZXN0IGFzc3VyZWQgdGhhdCBhbGwgbW9kZWxzIGFuZCBkYXRhIGhhdmUKCSAqIGJlZW4gdXBkYXRlZCBmcm9tIHRoZSBjaGFuZ2UgYnkgdGhlIHRpZW0gdGhleSBhcmUgbm90aWZpZWQuIFRoaXMgaXMKCSAqIGVzcGVjaWFsbHkgaW1wb3J0YW50IGZvciB0aGUgdGV4dCB3aWRnZXQsIGZvciBleGFtcGxlLCB3aGljaCBtYXkgcmVseQoJICogb24gYm90aCBzdHJ1Y3R1cmVkRG9jdW1lbnQgYW5kIHN0cnVjdHVyYWwgbW9kZWwgaW5mb3JtYXRpb24uCgkgKi8KCXB1YmxpYyB2b2lkIGFkZERvY3VtZW50Q2hhbmdlZExpc3RlbmVyKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpIHsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkTW9kZWxDaGFuZ2VkTGlzdGVuZXIuIFJlcXVlc3QgdG8gYWRkIGFuIGluc3RhbmNlIG9mICIgKyBsaXN0ZW5lci5nZXRDbGFzcygpICsgIiBhcyBhIGxpc3RlbmVyIG9uIHN0cnVjdHVyZWREb2N1bWVudC4iKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJfQoJCQkvLyBtYWtlIHN1cmUgbGlzdGVuZXIgaXMgbm90IGFscmVhZHkgaW4gbGlzdGVuaW5nCgkJCS8vIChhbmQgaWYgaXQgaXMsIHByaW50IGEgd2FybmluZyB0byBhaWQgZGVidWdnaW5nLCBpZiBuZWVkZWQpCgkJCWlmIChVdGlsaXRpZXMuY29udGFpbnMoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJaWYgKERlYnVnLmRpc3BsYXlXYXJuaW5ncykgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkTW9kZWxDaGFuZ2VkTGlzdGVuZXIuIGxpc3RlbmVyICIgKyBsaXN0ZW5lciArICIgd2FzIGFkZGVkZWQgbW9yZSB0aGFuIG9uY2UuICIpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJCWVsc2UgewoJCQkJaWYgKERlYnVnLmRlYnVnU3RydWN0dXJlZERvY3VtZW50KSB7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJJU3RydWN0dXJlZERvY3VtZW50OjphZGRNb2RlbENoYW5nZWRMaXN0ZW5lci4gQWRkaW5nIGFuIGluc3RhbmNlIG9mICIgKyBsaXN0ZW5lci5nZXRDbGFzcygpICsgIiBhcyBhIGxpc3RlbmVyIG9uIHN0cnVjdHVyZWREb2N1bWVudC4iKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJCWludCBvbGRTaXplID0gMDsKCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJLy8gbm9ybWFsbHkgd29uJ3QgYmUgbnVsbCwgYnV0IHdlIG5lZWQgdG8gYmUgc3VyZSwgZm9yCgkJCQkJLy8gZmlyc3QKCQkJCQkvLyB0aW1lIHRocm91Z2gKCQkJCQlvbGRTaXplID0gZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJfQoJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplICsgMTsKCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCVN5c3RlbS5hcnJheWNvcHkoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIDAsIG5ld0xpc3RlbmVycywgMCwgb2xkU2l6ZSk7CgkJCQl9CgkJCQkvLyBhZGQgbGlzdGVuZXIgdG8gbGFzdCBwb3NpdGlvbgoJCQkJbmV3TGlzdGVuZXJzW25ld1NpemUgLSAxXSA9IGxpc3RlbmVyOwoJCQkJLy8KCQkJCS8vIG5vdyBzd2l0Y2ggbmV3IGZvciBvbGQKCQkJCWZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJLy8KCQkJCS8vIHdoZW4gYSBsaXN0ZW5lciBpcyBhZGRlZCwKCQkJCS8vIHNlbmQgdGhlIG5ldyBtb2RlbCBldmVudCB0byB0aGF0IG9uZSBwYXJ0aWN1bGFyIGxpc3RlbmVyLAoJCQkJLy8gc28gaXQKCQkJCS8vIGNhbiBpbml0aWFsaXplIGl0c2VsZiB3aXRoIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBtb2RlbAoJCQkJLy8gbGlzdGVuZXIubmV3TW9kZWwobmV3IE5ld01vZGVsRXZlbnQodGhpcywgbGlzdGVuZXIpKTsKCQkJfQoJCX0KCX0KCglwdWJsaWMgdm9pZCBhZGREb2N1bWVudENoYW5naW5nTGlzdGVuZXIoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkgewoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJJU3RydWN0dXJlZERvY3VtZW50OjphZGRTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lci4gUmVxdWVzdCB0byBhZGQgYW4gaW5zdGFuY2Ugb2YgIiArIGxpc3RlbmVyLmdldENsYXNzKCkgKyAiIGFzIGEgbGlzdGVuZXIgb24gc3RydWN0dXJlZERvY3VtZW50LiIpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQl9CgkJCS8vIG1ha2Ugc3VyZSBsaXN0ZW5lciBpcyBub3QgYWxyZWFkeSBpbiBsaXN0ZW5pbmcKCQkJLy8gKGFuZCBpZiBpdCBpcywgcHJpbnQgYSB3YXJuaW5nIHRvIGFpZCBkZWJ1Z2dpbmcsIGlmIG5lZWRlZCkKCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJaWYgKERlYnVnLmRpc3BsYXlXYXJuaW5ncykgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIuIGxpc3RlbmVyICIgKyBsaXN0ZW5lciArICIgd2FzIGFkZGVkZWQgbW9yZSB0aGFuIG9uY2UuICIpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJCWVsc2UgewoJCQkJaWYgKERlYnVnLmRlYnVnU3RydWN0dXJlZERvY3VtZW50KSB7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJJU3RydWN0dXJlZERvY3VtZW50OjphZGRTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lci4gQWRkaW5nIGFuIGluc3RhbmNlIG9mICIgKyBsaXN0ZW5lci5nZXRDbGFzcygpICsgIiBhcyBhIGxpc3RlbmVyIG9uIHN0cnVjdHVyZWREb2N1bWVudC4iKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJCWludCBvbGRTaXplID0gMDsKCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCS8vIG5vcm1hbGx5IHdvbid0IGJlIG51bGwsIGJ1dCB3ZSBuZWVkIHRvIGJlIHN1cmUsIGZvcgoJCQkJCS8vIGZpcnN0CgkJCQkJLy8gdGltZSB0aHJvdWdoCgkJCQkJb2xkU2l6ZSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycy5sZW5ndGg7CgkJCQl9CgkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgKyAxOwoJCQkJT2JqZWN0W10gbmV3TGlzdGVuZXJzID0gbmV3IE9iamVjdFtuZXdTaXplXTsKCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCVN5c3RlbS5hcnJheWNvcHkoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCAwLCBuZXdMaXN0ZW5lcnMsIDAsIG9sZFNpemUpOwoJCQkJfQoJCQkJLy8gYWRkIGxpc3RlbmVyIHRvIGxhc3QgcG9zaXRpb24KCQkJCW5ld0xpc3RlbmVyc1tuZXdTaXplIC0gMV0gPSBsaXN0ZW5lcjsKCQkJCS8vCgkJCQkvLyBub3cgc3dpdGNoIG5ldyBmb3Igb2xkCgkJCQlmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQkvLwoJCQkJLy8gd2hlbiBhIGxpc3RlbmVyIGlzIGFkZGVkLAoJCQkJLy8gc2VuZCB0aGUgbmV3IG1vZGVsIGV2ZW50IHRvIHRoYXQgb25lIHBhcnRpY3VsYXIgbGlzdGVuZXIsCgkJCQkvLyBzbyBpdAoJCQkJLy8gY2FuIGluaXRpYWxpemUgaXRzZWxmIHdpdGggdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIG1vZGVsCgkJCQkvLyBsaXN0ZW5lci5uZXdNb2RlbChuZXcgTmV3TW9kZWxFdmVudCh0aGlzLCBsaXN0ZW5lcikpOwoJCQl9CgkJfQoJfQoKCS8qKgoJICogV2UgbWFuYWdlIG91ciBvd24gZG9jdW1lbnQgbGlzdG5lcnMsIGluc3RlYWQgb2YgZGVsZWdhdGluZyB0byBvdXIKCSAqIHBhcmVudERvY3VtZW50LCBzbyB3ZSBjYW4gZmlyZSBhdCB2ZXJ5IGVuZCAoYW5kIG5vdCB3aGVuIHRoZQoJICogcGFyZW50RG9jdW1lbnQgY2hhbmdlcykuCgkgKiAKCSAqLwoJcHVibGljIHZvaWQgYWRkRG9jdW1lbnRMaXN0ZW5lcihJRG9jdW1lbnRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQkvLyBtYWtlIHN1cmUgbGlzdGVuZXIgaXMgbm90IGFscmVhZHkgaW4gbGlzdGVuaW5nCgkJCS8vIChhbmQgaWYgaXQgaXMsIHByaW50IGEgd2FybmluZyB0byBhaWQgZGVidWdnaW5nLCBpZiBuZWVkZWQpCgkJCWlmICghVXRpbGl0aWVzLmNvbnRhaW5zKGZEb2N1bWVudExpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQlpbnQgb2xkU2l6ZSA9IDA7CgkJCQlpZiAoZkRvY3VtZW50TGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQkvLyBub3JtYWxseSB3b24ndCBiZSBudWxsLCBidXQgd2UgbmVlZCB0byBiZSBzdXJlLCBmb3IKCQkJCQkvLyBmaXJzdAoJCQkJCS8vIHRpbWUgdGhyb3VnaAoJCQkJCW9sZFNpemUgPSBmRG9jdW1lbnRMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJfQoJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplICsgMTsKCQkJCUlEb2N1bWVudExpc3RlbmVyW10gbmV3TGlzdGVuZXJzID0gbnVsbDsKCQkJCW5ld0xpc3RlbmVycyA9IG5ldyBJRG9jdW1lbnRMaXN0ZW5lcltuZXdTaXplXTsKCQkJCWlmIChmRG9jdW1lbnRMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCVN5c3RlbS5hcnJheWNvcHkoZkRvY3VtZW50TGlzdGVuZXJzLCAwLCBuZXdMaXN0ZW5lcnMsIDAsIG9sZFNpemUpOwoJCQkJfQoJCQkJLy8gYWRkIGxpc3RlbmVyIHRvIGxhc3QgcG9zaXRpb24KCQkJCW5ld0xpc3RlbmVyc1tuZXdTaXplIC0gMV0gPSBsaXN0ZW5lcjsKCQkJCS8vIG5vdyBzd2l0Y2ggbmV3IGZvciBvbGQKCQkJCWZEb2N1bWVudExpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJfQoJCX0KCX0KCgkvKgoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudCNhZGREb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIpCgkgKiAKCSAqIFJlZ2lzdGVycyB0aGUgZG9jdW1lbnQgcGFydGl0aW9uaW5nIGxpc3RlbmVyIHdpdGggdGhlIGRvY3VtZW50LiBBZnRlcgoJICogcmVnaXN0cmF0aW9uIHRoZSBJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lciBpcyBpbmZvcm1lZCBhYm91dCBlYWNoCgkgKiBwYXJ0aXRpb24gY2hhbmdlIGNhdXNlIGJ5IGEgZG9jdW1lbnQgbWFuaXB1bGF0aW9uLiBJZiBhIGRvY3VtZW50CgkgKiBwYXJ0aXRpb25pbmcgbGlzdGVuZXIgaXMgYWxzbyBhIGRvY3VtZW50IGxpc3RlbmVyLCB0aGUgZm9sbG93aW5nCgkgKiBub3RpZmljYXRpb24gc2VxdWVuY2UgaXMgZ3VhcmFudGVlZCBpZiBhIGRvY3VtZW50IG1hbmlwdWxhdGlvbiBjaGFuZ2VzCgkgKiB0aGUgZG9jdW1lbnQgcGFydGl0aW9uaW5nOiAxKQoJICogbGlzdGVuZXIuZG9jdW1lbnRBYm91dFRvQmVDaGFuZ2VkKERvY3VtZW50RXZlbnQpOyAyKQoJICogbGlzdGVuZXIuZG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkKCk7IDMpCgkgKiBsaXN0ZW5lci5kb2N1bWVudENoYW5nZWQoRG9jdW1lbnRFdmVudCk7IElmIHRoZSBsaXN0ZW5lciBpcyBhbHJlYWR5CgkgKiByZWdpc3RlcmVkIG5vdGhpbmcgaGFwcGVucy4KCSAqIAoJICogQHNlZSBJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcgoJICovCgoJcHVibGljIHZvaWQgYWRkRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcihJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlBc3NlcnQuaXNOb3ROdWxsKGxpc3RlbmVyKTsKCQkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycyA9PSBudWxsKSB7CgkJCQlmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMgPSBuZXcgQXJyYXlMaXN0KDEpOwoJCQl9CgkJCWlmICghZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzLmNvbnRhaW5zKGxpc3RlbmVyKSkKCQkJCWZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycy5hZGQobGlzdGVuZXIpOwoJCX0KCX0KCgkvKioKCSAqIEFkZHMgdGhlIHBvc2l0aW9uIHRvIHRoZSBkb2N1bWVudCdzIGRlZmF1bHQgcG9zaXRpb24gY2F0ZWdvcnkuIFRoZQoJICogZGVmYXVsdCBjYXRlZ29yeSBtdXN0IGJlIHNwZWNpZmllZCBieSB0aGUgaW1wbGVtZW50ZXIuIEEgcG9zaXRpb24gdGhhdAoJICogaGFzIGJlZW4gYWRkZWQgdG8gYSBwb3NpdGlvbiBjYXRlZ29yeSBpcyB1cGRhdGVkIGF0IGVhY2ggY2hhbmdlIGFwcGxpZWQKCSAqIHRvIHRoZSBkb2N1bWVudC4KCSAqIAoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgcG9zaXRpb24gaXMgbm90IGEgdmFsaWQgcmFuZ2UgaW4gdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyB2b2lkIGFkZFBvc2l0aW9uKFBvc2l0aW9uIHBvc2l0aW9uKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLmFkZFBvc2l0aW9uKHBvc2l0aW9uKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2FkZFBvc2l0aW9uCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiBwb3NpdGlvbiBpcyBub3QgYSB2YWxpZCByYW5nZSBpbiB0aGUgZG9jdW1lbnQKCSAqIEBleGNlcHRpb24gQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgdGhlIGNhdGVnb3J5IGlzIG5vdCBkZWZpbmVkIGZvciB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIHZvaWQgYWRkUG9zaXRpb24oU3RyaW5nIGNhdGVnb3J5LCBQb3NpdGlvbiBwb3NpdGlvbikgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uLCBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5hZGRQb3NpdGlvbihjYXRlZ29yeSwgcG9zaXRpb24pOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjYWRkUG9zaXRpb25DYXRlZ29yeQoJICovCglwdWJsaWMgdm9pZCBhZGRQb3NpdGlvbkNhdGVnb3J5KFN0cmluZyBjYXRlZ29yeSkgewoJCWludGVybmFsX2FkZFBvc2l0aW9uQ2F0ZWdvcnkoY2F0ZWdvcnkpOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjYWRkUG9zaXRpb25VcGRhdGVyCgkgKi8KCXB1YmxpYyB2b2lkIGFkZFBvc2l0aW9uVXBkYXRlcihJUG9zaXRpb25VcGRhdGVyIHVwZGF0ZXIpIHsKCQlpbnRlcm5hbF9hZGRQb3NpdGlvblVwZGF0ZXIodXBkYXRlcik7Cgl9CgoJLyoqCgkgKiBBZGRzIHRoZSBnaXZlbiBkb2N1bWVudCBsaXN0ZW5lciBhcyBvbmUgd2hpY2ggaXMgbm90aWZpZWQgYmVmb3JlIHRob3NlCgkgKiBkb2N1bWVudCBsaXN0ZW5lcnMgYWRkZWQgd2l0aCA8Y29kZT5hZGREb2N1bWVudExpc3RlbmVyPC9jb2RlPiBhcmUKCSAqIG5vdGlmaWVkLiBJZiB0aGUgZ2l2ZW4gbGlzdGVuZXIgaXMgYWxzbyByZWdpc3RlcmVkIHVzaW5nCgkgKiA8Y29kZT5hZGREb2N1bWVudExpc3RlbmVyPC9jb2RlPiBpdCB3aWxsIGJlIG5vdGlmaWVkIHR3aWNlLiBJZiB0aGUKCSAqIGxpc3RlbmVyIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCBub3RoaW5nIGhhcHBlbnMuCgkgKiA8cD4KCSAqIAoJICogVGhpcyBtZXRob2QgaXMgbm90IGZvciBwdWJsaWMgdXNlLCBpdCBtYXkgb25seSBiZSBjYWxsZWQgYnkKCSAqIGltcGxlbWVudGVycyBvZiA8Y29kZT5JRG9jdW1lbnRBZGFwdGVyPC9jb2RlPiBhbmQgb25seSBpZiB0aG9zZQoJICogaW1wbGVtZW50ZXJzIG5lZWQgdG8gaW1wbGVtZW50IDxjb2RlPklEb2N1bWVudExpc3RlbmVyPC9jb2RlPi4KCSAqIAoJICogQHBhcmFtIGRvY3VtZW50QWRhcHRlcgoJICogICAgICAgICAgICB0aGUgbGlzdGVuZXIgdG8gYmUgYWRkZWQgYXMgcHJlbm90aWZpZWQgZG9jdW1lbnQgbGlzdGVuZXIKCSAqLwoJcHVibGljIHZvaWQgYWRkUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVyKElEb2N1bWVudExpc3RlbmVyIGRvY3VtZW50QWRhcHRlcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJaW50IHByZXZpb3VzU2l6ZSA9IGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLmxlbmd0aDsKCQkJCUlEb2N1bWVudExpc3RlbmVyW10gbGlzdGVuZXJzID0gbmV3IElEb2N1bWVudExpc3RlbmVyW3ByZXZpb3VzU2l6ZSArIDFdOwoJCQkJU3lzdGVtLmFycmF5Y29weShmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgMCwgbGlzdGVuZXJzLCAwLCBwcmV2aW91c1NpemUpOwoJCQkJbGlzdGVuZXJzW3ByZXZpb3VzU2l6ZV0gPSBkb2N1bWVudEFkYXB0ZXI7CgkJCQlmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJfQoJCQllbHNlIHsKCQkJCWZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzID0gbmV3IElEb2N1bWVudExpc3RlbmVyWzFdOwoJCQkJZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnNbMF0gPSBkb2N1bWVudEFkYXB0ZXI7CgkJCX0KCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBqYXZhLmxhbmcuQ2hhclNlcXVlbmNlI2NoYXJBdChpbnQpCgkgKi8KCXB1YmxpYyBjaGFyIGNoYXJBdChpbnQgYXJnMCkgewoJCXRyeSB7CgkJCXJldHVybiBnZXRDaGFyKDApOwoJCX0KCQljYXRjaCAoQmFkTG9jYXRpb25FeGNlcHRpb24gZSkgewoJCQl0aHJvdyBuZXcgSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbigpOwoJCX0KCX0KCgkvKioKCSAqIFRoaXMgZm9ybSBvZiB0aGUgQVBJIHJlbW92ZXMgYWxsIHJlYWQgb25seSBwb3NpdGlvbnMsIGFzIHNob3VsZCBiZSBkb25lCgkgKiB3ZSAnc2V0VGV4dCcgaXMgY2FsbGVkLiBOb3RlOiBhbiBhbHRlcm5hdGl2ZSBhbGdvcml0aG0gbWF5IHNpbXBseQoJICogcmVtb3ZlIHRoZSBjYXRlZ29yeSAoYW5kIGl0IHdvdWxkIGdldCBhZGRlZCBiYWNrIGluIGxhdGVyLCBpZi93aGVuCgkgKiByZWFkb25seSByZWdpb25zIGFkZGVkLgoJICovCglwcml2YXRlIHZvaWQgY2xlYXJSZWFkT25seSgpIHsKCQlQb3NpdGlvbltdIHBvc2l0aW9ucyA9IG51bGw7CgkJdHJ5IHsKCQkJcG9zaXRpb25zID0gZ2V0UG9zaXRpb25zKFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZKTsKCQl9CgkJY2F0Y2ggKEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gZSkgewoJCQlMb2dnZXIubG9nRXhjZXB0aW9uKCJwcm9ncmFtIGVycm9yOiBzaG91bGQgbmV2ZXIgb2NjdXIiLCBlKTsgLy8kTk9OLU5MUy0xJAoJCX0KCQlmb3IgKGludCBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkrKykgewoJCQlQb3NpdGlvbiBwb3NpdGlvbiA9IHBvc2l0aW9uc1tpXTsKCQkJLy8gbm90ZSB3ZSBkb24ndCBmaXJlIHRoZSAiYWJvdXQgdG8gY2hhbmdlIiBvciAiY2hhbmdlZCIgZXZlbnRzLAoJCQkvLyBzaW5jZSBwcmVzdW1hYmx5LCB0ZXh0IGlzIGFsbCBnb2luZyBhd2F5IGFuZCBiZWluZyByZXBsYWNlZAoJCQkvLyBhbnl3YXkuCgkJCXBvc2l0aW9uLmRlbGV0ZSgpOwoJCX0KCX0KCgoJcHVibGljIHZvaWQgY2xlYXJSZWFkT25seShpbnQgc3RhcnRPZmZzZXQsIGludCBsZW5ndGgpIHsKCQkvLyBUT0RPIERXIEkgc3RpbGwgbmVlZCB0byBpbXBsZW1lbnQgc21hcnRlciBhbGdvcml0aG0gdGhhdAoJCS8vIGFkdXN0IGV4aXN0aW5nIFJPIHJlZ2lvbnMsIGlmIG5lZWRlZC4gRm9yIG5vdywgSSdsbCBqdXN0CgkJLy8gcmVtb3ZlIGFueSB0aGF0IG92ZXJsYXAuCgkJdHJ5IHsKCQkJUG9zaXRpb25bXSBwb3NpdGlvbnMgPSBnZXRQb3NpdGlvbnMoUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlkpOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkrKykgewoJCQkJUG9zaXRpb24gcG9zaXRpb24gPSBwb3NpdGlvbnNbaV07CgkJCQlpZiAocG9zaXRpb24ub3ZlcmxhcHNXaXRoKHN0YXJ0T2Zmc2V0LCBsZW5ndGgpKSB7CgkJCQkJU3RyaW5nIGVmZmVjdGVkVGV4dCA9IHRoaXMuZ2V0KHN0YXJ0T2Zmc2V0LCBsZW5ndGgpOwoJCQkJCS8vIGZEb2N1bWVudEV2ZW50ID0gbmV3IERvY3VtZW50RXZlbnQodGhpcywgc3RhcnRPZmZzZXQsCgkJCQkJLy8gbGVuZ3RoLCBlZmZlY3RlZFRleHQpOwoJCQkJCWZpcmVSZWFkT25seUFib3V0VG9CZUNoYW5nZWQoKTsKCQkJCQlwb3NpdGlvbi5kZWxldGUoKTsKCQkJCQlOb0NoYW5nZUV2ZW50IG5vQ2hhbmdlRXZlbnQgPSBuZXcgTm9DaGFuZ2VFdmVudCh0aGlzLCBudWxsLCBlZmZlY3RlZFRleHQsIHN0YXJ0T2Zmc2V0LCBsZW5ndGgpOwoJCQkJCW5vQ2hhbmdlRXZlbnQucmVhc29uID0gTm9DaGFuZ2VFdmVudC5SRUFEX09OTFlfU1RBVEVfQ0hBTkdFOwoJCQkJCWZpcmVSZWFkT25seVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KG5vQ2hhbmdlRXZlbnQpOwoJCQkJfQoJCQl9CgkJfQoJCWNhdGNoIChCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIGUpIHsKCQkJLy8ganVzdCBtZWFucyBubyByZWFkb25seSByZWdpb25zIGJlZW4gZGVmaW5lZCB5ZXQKCQkJLy8gc28gbm90aGluZyB0byBkby4KCQl9Cgl9CgoJLyoqCgkgKiBDb21wdXRlcyB0aGUgaW5kZXggYXQgd2hpY2ggYSA8Y29kZT5Qb3NpdGlvbjwvY29kZT4gd2l0aCB0aGUKCSAqIHNwZWNpZmllZCBvZmZzZXQgd291bGQgYmUgaW5zZXJ0ZWQgaW50byB0aGUgZ2l2ZW4gY2F0ZWdvcnkuIEFzIHRoZQoJICogb3JkZXJpbmcgaW5zaWRlIGEgY2F0ZWdvcnkgb25seSBkZXBlbmRzIG9uIHRoZSBvZmZzZXQsIHRoZSBpbmRleCBtdXN0CgkgKiBiZSBjaG9vc2VuIHRvIGJlIHRoZSBmaXJzdCBvZiBhbGwgcG9zaXRpb25zIHdpdGggdGhlIHNhbWUgb2Zmc2V0LgoJICogCgkgKiBAcGFyYW0gY2F0ZWdvcnkKCSAqICAgICAgICAgICAgdGhlIGNhdGVnb3J5IGluIHdoaWNoIHdvdWxkIGJlIGFkZGVkCgkgKiBAcGFyYW0gb2Zmc2V0CgkgKiAgICAgICAgICAgIHRoZSBwb3NpdGlvbiBvZmZzZXQgdG8gYmUgY29uc2lkZXJlZAoJICogQHJldHVybiB0aGUgaW5kZXggaW50byB0aGUgY2F0ZWdvcnkKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIG9mZnNldCBpcyBpbnZhbGlkIGluIHRoaXMgZG9jdW1lbnQKCSAqIEBleGNlcHRpb24gQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgaWYgY2F0ZWdvcnkgaXMgdW5kZWZpbmVkIGluIHRoaXMgZG9jdW1lbnQKCSAqLwoJcHVibGljIGludCBjb21wdXRlSW5kZXhJbkNhdGVnb3J5KFN0cmluZyBjYXRlZ29yeSwgaW50IG9mZnNldCkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiwgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFBvc2l0aW9uTWFuYWdlcigpLmNvbXB1dGVJbmRleEluQ2F0ZWdvcnkoY2F0ZWdvcnksIG9mZnNldCk7Cgl9CgoJLyoqCgkgKiBDb21wdXRlcyB0aGUgbnVtYmVyIG9mIGxpbmVzIGluIHRoZSBnaXZlbiB0ZXh0LiBGb3IgYSBnaXZlbiBpbXBsZW1lbnRlcgoJICogb2YgdGhpcyBpbnRlcmZhY2UgdGhpcyBtZXRob2QgcmV0dXJucyB0aGUgc2FtZSByZXN1bHQgYXMKCSAqIDxjb2RlPnNldCh0ZXh0KTsgZ2V0TnVtYmVyT2ZMaW5lcygpPC9jb2RlPi4KCSAqIAoJICogQHBhcmFtIHRleHQKCSAqICAgICAgICAgICAgdGhlIHRleHQgd2hvc2UgbnVtYmVyIG9mIGxpbmVzIHNob3VsZCBiZSBjb21wdXRlZAoJICogQHJldHVybiB0aGUgbnVtYmVyIG9mIGxpbmVzIGluIHRoZSBnaXZlbiB0ZXh0CgkgKi8KCXB1YmxpYyBpbnQgY29tcHV0ZU51bWJlck9mTGluZXMoU3RyaW5nIHRleHQpIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmNvbXB1dGVOdW1iZXJPZkxpbmVzKHRleHQpOwoJfQoKCS8qKgoJICogQ29tcHV0ZXMgdGhlIHBhcnRpdGlvbmluZyBvZiB0aGUgZ2l2ZW4gZG9jdW1lbnQgcmFuZ2UgdXNpbmcgdGhlCgkgKiBkb2N1bWVudCdzIHBhcnRpdGlvbmVyLgoJICogCgkgKiBAcGFyYW0gb2Zmc2V0CgkgKiAgICAgICAgICAgIHRoZSBkb2N1bWVudCBvZmZzZXQgYXQgd2hpY2ggdGhlIHJhbmdlIHN0YXJ0cwoJICogQHBhcmFtIGxlbmd0aAoJICogICAgICAgICAgICB0aGUgbGVuZ3RoIG9mIHRoZSBkb2N1bWVudCByYW5nZQoJICogQHJldHVybiBhIHNwZWNpZmljYXRpb24gb2YgdGhlIHJhbmdlJ3MgcGFydGl0aW9uaW5nCgkgKiBAdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiBAdGhyb3dzIEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbgoJICovCglwdWJsaWMgSVR5cGVkUmVnaW9uW10gY29tcHV0ZVBhcnRpdGlvbmluZyhpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCUlUeXBlZFJlZ2lvbltdIHR5cGVkUmVnaW9ucyA9IG51bGw7CgkJdHJ5IHsKCQkJdHlwZWRSZWdpb25zID0gY29tcHV0ZVBhcnRpdGlvbmluZyhJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HLCBvZmZzZXQsIGxlbmd0aCwgZmFsc2UpOwoJCX0KCQljYXRjaCAoQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIGUpIHsKCQkJLy8gaW1wb3NzaWJsZSBpbiB0aGlzIGNvbnRleHQKCQkJdGhyb3cgbmV3IEVycm9yKGUpOwoJCX0KCQlpZiAodHlwZWRSZWdpb25zID09IG51bGwpIHsKCQkJdHlwZWRSZWdpb25zID0gbmV3IElUeXBlZFJlZ2lvblswXTsKCQl9CgkJcmV0dXJuIHR5cGVkUmVnaW9uczsKCX0KCgoJcHVibGljIElUeXBlZFJlZ2lvbltdIGNvbXB1dGVQYXJ0aXRpb25pbmcoU3RyaW5nIHBhcnRpdGlvbmluZywgaW50IG9mZnNldCwgaW50IGxlbmd0aCwgYm9vbGVhbiBpbmNsdWRlWmVyb0xlbmd0aFBhcnRpdGlvbnMpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiwgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIHsKCQlpZiAoKDAgPiBvZmZzZXQpIHx8ICgwID4gbGVuZ3RoKSB8fCAob2Zmc2V0ICsgbGVuZ3RoID4gZ2V0TGVuZ3RoKCkpKQoJCQl0aHJvdyBuZXcgQmFkTG9jYXRpb25FeGNlcHRpb24oKTsKCgkJSURvY3VtZW50UGFydGl0aW9uZXIgcGFydGl0aW9uZXIgPSBnZXREb2N1bWVudFBhcnRpdGlvbmVyKHBhcnRpdGlvbmluZyk7CgoJCWlmIChwYXJ0aXRpb25lciBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMikKCQkJcmV0dXJuICgoSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKSBwYXJ0aXRpb25lcikuY29tcHV0ZVBhcnRpdGlvbmluZyhvZmZzZXQsIGxlbmd0aCwgaW5jbHVkZVplcm9MZW5ndGhQYXJ0aXRpb25zKTsKCQllbHNlIGlmIChwYXJ0aXRpb25lciAhPSBudWxsKQoJCQlyZXR1cm4gcGFydGl0aW9uZXIuY29tcHV0ZVBhcnRpdGlvbmluZyhvZmZzZXQsIGxlbmd0aCk7CgkJZWxzZSBpZiAoSVN0cnVjdHVyZWRQYXJ0aXRpb25pbmcuREVGQVVMVF9TVFJVQ1RVUkVEX1BBUlRJVElPTklORy5lcXVhbHMocGFydGl0aW9uaW5nKSkKCQkJcmV0dXJuIG5ldyBUeXBlZFJlZ2lvbltde25ldyBUeXBlZFJlZ2lvbihvZmZzZXQsIGxlbmd0aCwgREVGQVVMVF9DT05URU5UX1RZUEUpfTsKCQllbHNlCgkJCXRocm93IG5ldyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24oKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2NvbnRhaW5zUG9zaXRpb24KCSAqLwoJcHVibGljIGJvb2xlYW4gY29udGFpbnNQb3NpdGlvbihTdHJpbmcgY2F0ZWdvcnksIGludCBvZmZzZXQsIGludCBsZW5ndGgpIHsKCQlyZXR1cm4gZ2V0UG9zaXRpb25NYW5hZ2VyKCkuY29udGFpbnNQb3NpdGlvbihjYXRlZ29yeSwgb2Zmc2V0LCBsZW5ndGgpOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjY29udGFpbnNQb3NpdGlvbkNhdGVnb3J5CgkgKi8KCXB1YmxpYyBib29sZWFuIGNvbnRhaW5zUG9zaXRpb25DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnkpIHsKCQlyZXR1cm4gZ2V0UG9zaXRpb25NYW5hZ2VyKCkuY29udGFpbnNQb3NpdGlvbkNhdGVnb3J5KGNhdGVnb3J5KTsKCX0KCglwdWJsaWMgYm9vbGVhbiBjb250YWluc1JlYWRPbmx5KGludCBzdGFydE9mZnNldCwgaW50IGxlbmd0aCkgewoJCWJvb2xlYW4gcmVzdWx0ID0gZmFsc2U7CgkJdHJ5IHsKCQkJUG9zaXRpb25bXSBwb3NpdGlvbnMgPSBnZXRQb3NpdGlvbnMoUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlkpOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkrKykgewoJCQkJUG9zaXRpb24gcG9zaXRpb24gPSBwb3NpdGlvbnNbaV07CgkJCQlpZiAocG9zaXRpb24ub3ZlcmxhcHNXaXRoKHN0YXJ0T2Zmc2V0LCBsZW5ndGgpKSB7CgkJCQkJcmVzdWx0ID0gdHJ1ZTsKCQkJCQlicmVhazsKCQkJCX0KCQkJfQoJCX0KCQljYXRjaCAoQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiBlKSB7CgkJCS8vIGp1c3QgbWVhbnMgbm8gcmVhZG9ubHkgcmVnaW9ucyBiZWVuIGRlZmluZWQgeWV0CgkJCS8vIHNvIG9idmlvdXNseSBmYWxzZQoJCQlyZXN1bHQgPSBmYWxzZTsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCglwcml2YXRlIHZvaWQgZXhlY3V0ZVBvc3ROb3RpZmljYXRpb25DaGFuZ2VzKCkgewoJCWlmIChmU3RvcHBlZENvdW50ID4gMCkKCQkJcmV0dXJuOwoJCXdoaWxlIChmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMgIT0gbnVsbCkgewoJCQlMaXN0IGNoYW5nZXMgPSBmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXM7CgkJCWZQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlcyA9IG51bGw7CgkJCUl0ZXJhdG9yIGUgPSBjaGFuZ2VzLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChlLmhhc05leHQoKSkgewoJCQkJUmVnaXN0ZXJlZFJlcGxhY2UgcmVwbGFjZSA9IChSZWdpc3RlcmVkUmVwbGFjZSkgZS5uZXh0KCk7CgkJCQlyZXBsYWNlLmZSZXBsYWNlLnBlcmZvcm0odGhpcywgcmVwbGFjZS5mT3duZXIpOwoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBmaXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlZCgpIHsKCQkvLyBtb3N0IERvY3VtZW50QWJvdXRUb0JlQ2hhbmdlZCBsaXN0ZW5lcnMgZG8gbm90IGFudGljaXBhdGUKCQkvLyBEb2N1bWVudEV2ZW50ID09IG51bGwuIFNvIG1ha2Ugc3VyZSBkb2N1bWVudEV2ZW50IGlzIG5vdAoJCS8vIG51bGwuICh0aGlzIHNob3VsZCBuZXZlciBoYXBwZW4sIHlldCBpdCBkb2VzIHNvbWV0aW1lcykKCQlpZiAoZkRvY3VtZW50RXZlbnQgPT0gbnVsbCkgewoJCQlmRG9jdW1lbnRFdmVudCA9IG5ldyBOdWxsRG9jdW1lbnRFdmVudCgpOwoJCX0KCgkJX2ZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzKTsKCQkvLyBOb3RlOiB0aGUgZG9jRXZlbnQgaXMgY3JlYXRlZCBpbiByZXBsYWNlVGV4dCBBUEkhIChvciBzZXQgVGV4dCkKCQlfZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZShmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycyk7CgkJbm90aWZ5RG9jdW1lbnRQYXJ0aXRpb25lcnNBYm91dFRvQ2hhbmdlKGZEb2N1bWVudEV2ZW50KTsKCQlfZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZShmRG9jdW1lbnRMaXN0ZW5lcnMpOwoJfQoKCS8qKgoJICogRmlyZXMgdGhlIGRvY3VtZW50IHBhcnRpdGlvbmluZyBjaGFuZ2VkIG5vdGlmaWNhdGlvbiB0byBhbGwgcmVnaXN0ZXJlZAoJICogZG9jdW1lbnQgcGFydGl0aW9uaW5nIGxpc3RlbmVycy4gVXNlcyBhIHJvYnVzdCBpdGVyYXRvci4KCSAqIAoJICogQHBhcmFtIGV2ZW50CgkgKiAgICAgICAgICAgIHRoZSBkb2N1bWVudCBwYXJ0aXRpb25pbmcgY2hhbmdlZCBldmVudAoJICogCgkgKiBAc2VlIElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uMgoJICovCglwcm90ZWN0ZWQgdm9pZCBmaXJlRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkKERvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZEV2ZW50IGV2ZW50KSB7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycyA9PSBudWxsIHx8IGZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycy5zaXplKCkgPT0gMCkKCQkJcmV0dXJuOwoKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KGZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycyk7CgkJSXRlcmF0b3IgZSA9IGxpc3QuaXRlcmF0b3IoKTsKCQl3aGlsZSAoZS5oYXNOZXh0KCkpIHsKCQkJSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIgbCA9IChJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcikgZS5uZXh0KCk7CgkJCWlmIChsIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24yKSB7CgkJCQlJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbjIgZXh0ZW5zaW9uMiA9IChJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbjIpIGw7CgkJCQlleHRlbnNpb24yLmRvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZChldmVudCk7CgkJCX0KCQkJZWxzZSBpZiAobCBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uKSB7CgkJCQlJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbiBleHRlbnNpb24gPSAoSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24pIGw7CgkJCQlleHRlbnNpb24uZG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkKHRoaXMsIGV2ZW50LmdldENvdmVyYWdlKCkpOwoJCQl9CgkJCWVsc2UgewoJCQkJbC5kb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWQodGhpcyk7CgkJCX0KCQl9CgoJfQoKCXByaXZhdGUgdm9pZCBmaXJlUmVhZE9ubHlBYm91dFRvQmVDaGFuZ2VkKCkgewoJCV9maXJlU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZShmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyk7CgkJLy8gTm90ZTogdGhlIGRvY0V2ZW50IGlzIGNyZWF0ZWQgaW4gcmVwbGFjZVRleHQgQVBJISAob3Igc2V0IFRleHQpCgkJLy8gX2ZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2UoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMpOwoJCS8vIF9maXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlKGZEb2N1bWVudExpc3RlbmVycyk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVSZWFkT25seVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KE5vQ2hhbmdlRXZlbnQgZXZlbnQpIHsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIGV2ZW50KTsKCQkvLyBfZmlyZURvY3VtZW50Q2hhbmdlZChmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCS8vIF9maXJlRG9jdW1lbnRDaGFuZ2VkKGZEb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCS8vIF9jbGVhckRvY3VtZW50RXZlbnQoKTsKCX0KCglwcml2YXRlIHZvaWQgZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KE5vQ2hhbmdlRXZlbnQgZXZlbnQpIHsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCW5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzRG9jdW1lbnRDaGFuZ2VkKGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfY2xlYXJEb2N1bWVudEV2ZW50KCk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChSZWdpb25DaGFuZ2VkRXZlbnQgZXZlbnQpIHsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCW5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzRG9jdW1lbnRDaGFuZ2VkKGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfY2xlYXJEb2N1bWVudEV2ZW50KCk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChSZWdpb25zUmVwbGFjZWRFdmVudCBldmVudCkgewoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJbm90aWZ5RG9jdW1lbnRQYXJ0aXRpb25lcnNEb2N1bWVudENoYW5nZWQoZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZEb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCV9jbGVhckRvY3VtZW50RXZlbnQoKTsKCX0KCglwcml2YXRlIHZvaWQgZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50IGV2ZW50KSB7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0RvY3VtZW50Q2hhbmdlZChldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZkRvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJX2NsZWFyRG9jdW1lbnRFdmVudCgpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgZG9jdW1lbnQncyBjb21wbGV0ZSB0ZXh0LgoJICovCglwdWJsaWMgU3RyaW5nIGdldCgpIHsKCQlyZXR1cm4gZ2V0U3RvcmUoKS5nZXQoMCwgZ2V0TGVuZ3RoKCkpOwoJfQoKCS8qKgoJICogUmV0dXJucyBsZW5ndGggY2hhcmFjdGVycyBmcm9tIHRoZSBkb2N1bWVudCdzIHRleHQgc3RhcnRpbmcgZnJvbSB0aGUKCSAqIHNwZWNpZmllZCBwb3NpdGlvbi4KCSAqIAoJICogQHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiB0aGUgcmFuZ2UgaXMgbm90IHZhbGlkIGluIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgU3RyaW5nIGdldChpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJU3RyaW5nIHJlc3VsdCA9IG51bGw7CgkJaW50IG15TGVuZ3RoID0gZ2V0TGVuZ3RoKCk7CgkJaWYgKDAgPiBvZmZzZXQpCgkJCW9mZnNldCA9IDA7CgkJaWYgKDAgPiBsZW5ndGgpCgkJCWxlbmd0aCA9IDA7CgkJaWYgKG9mZnNldCArIGxlbmd0aCA+IG15TGVuZ3RoKSB7CgkJCS8vIGZpcnN0IHRyeSBhZGp1c3RpbmcgbGVuZ3RoIHRvIGZpdAoJCQlpbnQgbGVzc0xlbmd0aCA9IG15TGVuZ3RoIC0gb2Zmc2V0OwoJCQlpZiAoKGxlc3NMZW5ndGggPj0gMCkgJiYgKG9mZnNldCArIGxlc3NMZW5ndGggPT0gbXlMZW5ndGgpKSB7CgkJCQlsZW5ndGggPSBsZXNzTGVuZ3RoOwoJCQl9CgkJCWVsc2UgewoJCQkJLy8gc2Vjb25kLCB0cnkgb2Zmc2V0CgkJCQlpbnQgbW9yZU9mZnNldCA9IG15TGVuZ3RoIC0gbGVuZ3RoOwoJCQkJaWYgKChtb3JlT2Zmc2V0ID49IDApICYmIChtb3JlT2Zmc2V0ICsgbGVuZ3RoID09IG15TGVuZ3RoKSkgewoJCQkJCW9mZnNldCA9IG1vcmVPZmZzZXQ7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQkvLyBjYW4gaGFwcGVuIGlmIG15TGVuZ3RoIGlzIDAuCgkJCQkJLy8gbm8gYWRqdXN0bWVudCBwb3NzaWJsZS4KCQkJCQlyZXN1bHQgPSBuZXcgU3RyaW5nKCk7CgkJCQl9CgkJCX0KCgkJfQoJCWlmIChyZXN1bHQgPT0gbnVsbCkgewoJCQlyZXN1bHQgPSBnZXRTdG9yZSgpLmdldChvZmZzZXQsIGxlbmd0aCk7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJcHVibGljIE9iamVjdCBnZXRBZGFwdGVyKENsYXNzIGFkYXB0ZXIpIHsKCQlyZXR1cm4gUGxhdGZvcm0uZ2V0QWRhcHRlck1hbmFnZXIoKS5nZXRBZGFwdGVyKHRoaXMsIGFkYXB0ZXIpOwoJfQoKCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKSB7CgkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZXN1bHQgPSBudWxsOwoJCWlmIChVU0VfTE9DQUxfVEhSRUFEKSB7CgkJCXJlc3VsdCA9IGZDdXJyZW50RG9jdW1uZXRSZWdpb25DYWNoZS5nZXQoKTsKCQl9CgkJZWxzZSB7CgkJCXJlc3VsdCA9IGNhY2hlZERvY3VtZW50UmVnaW9uOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjZ2V0Q2hhcgoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgcG9zaXRpb24gaXMgbm90IGEgdmFsaWQgcmFuZ2UgaW4gdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBjaGFyIGdldENoYXIoaW50IHBvcykgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQljaGFyIHJlc3VsdCA9IDB4MDA7CgkJdHJ5IHsKCQkJcmVzdWx0ID0gZ2V0U3RvcmUoKS5nZXQocG9zKTsKCQl9CgkJY2F0Y2ggKEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gZSkgewoJCQl0aHJvdyBuZXcgQmFkTG9jYXRpb25FeGNlcHRpb24oZS5nZXRMb2NhbGl6ZWRNZXNzYWdlKCkpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgdHlwZSBvZiB0aGUgZG9jdW1lbnQgcGFydGl0aW9uIGNvbnRhaW5pbmcgdGhlIGdpdmVuCgkgKiBjaGFyYWN0ZXIgcG9zaXRpb24uCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0Q29udGVudFR5cGUoaW50IG9mZnNldCkgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcigpLmdldENvbnRlbnRUeXBlKG9mZnNldCk7Cgl9CgoKCXB1YmxpYyBTdHJpbmcgZ2V0Q29udGVudFR5cGUoU3RyaW5nIHBhcnRpdGlvbmluZywgaW50IG9mZnNldCwgYm9vbGVhbiBwcmVmZXJPcGVuUGFydGl0aW9ucykgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uLCBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24gewoJCWlmICgoMCA+IG9mZnNldCkgfHwgKG9mZnNldCA+IGdldExlbmd0aCgpKSkKCQkJdGhyb3cgbmV3IEJhZExvY2F0aW9uRXhjZXB0aW9uKCk7CgoJCUlEb2N1bWVudFBhcnRpdGlvbmVyIHBhcnRpdGlvbmVyID0gZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcihwYXJ0aXRpb25pbmcpOwoKCQlpZiAocGFydGl0aW9uZXIgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjIpCgkJCXJldHVybiAoKElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMikgcGFydGl0aW9uZXIpLmdldENvbnRlbnRUeXBlKG9mZnNldCwgcHJlZmVyT3BlblBhcnRpdGlvbnMpOwoJCWVsc2UgaWYgKHBhcnRpdGlvbmVyICE9IG51bGwpCgkJCXJldHVybiBwYXJ0aXRpb25lci5nZXRDb250ZW50VHlwZShvZmZzZXQpOwoJCWVsc2UgaWYgKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcuZXF1YWxzKHBhcnRpdGlvbmluZykpCgkJCXJldHVybiBERUZBVUxUX0NPTlRFTlRfVFlQRTsKCQllbHNlCgkJCXRocm93IG5ldyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24oKTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNnZXREZWZhdWx0TGluZURlbGltaXRlcigpCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0RGVmYXVsdExpbmVEZWxpbWl0ZXIoKSB7CgkJCgkJU3RyaW5nIGxpbmVEZWxpbWl0ZXI9IG51bGw7CgkJCgkJdHJ5IHsKCQkJbGluZURlbGltaXRlcj0gZ2V0TGluZURlbGltaXRlcigwKTsKCQl9IGNhdGNoIChCYWRMb2NhdGlvbkV4Y2VwdGlvbiB4KSB7CgkJfQoJCgkJaWYgKGxpbmVEZWxpbWl0ZXIgIT0gbnVsbCkKCQkJcmV0dXJuIGxpbmVEZWxpbWl0ZXI7CgoJCWlmIChmSW5pdGlhbExpbmVEZWxpbWl0ZXIgIT0gbnVsbCkKCQkJcmV0dXJuIGZJbml0aWFsTGluZURlbGltaXRlcjsKCgkJU3RyaW5nIHN5c0xpbmVEZWxpbWl0ZXI9IFN5c3RlbS5nZXRQcm9wZXJ0eSgibGluZS5zZXBhcmF0b3IiKTsgLy8kTk9OLU5MUy0xJAoJCVN0cmluZ1tdIGRlbGltaXRlcnM9IGdldExlZ2FsTGluZURlbGltaXRlcnMoKTsKCQlBc3NlcnQuaXNUcnVlKGRlbGltaXRlcnMubGVuZ3RoID4gMCk7CgkJZm9yIChpbnQgaT0gMDsgaSA8IGRlbGltaXRlcnMubGVuZ3RoOyBpKyspIHsKCQkJaWYgKGRlbGltaXRlcnNbaV0uZXF1YWxzKHN5c0xpbmVEZWxpbWl0ZXIpKSB7CgkJCQlsaW5lRGVsaW1pdGVyPSBzeXNMaW5lRGVsaW1pdGVyOwoJCQkJYnJlYWs7CgkJCX0KCQl9CgkJCgkJaWYgKGxpbmVEZWxpbWl0ZXIgPT0gbnVsbCkKCQkJbGluZURlbGltaXRlcj0gZGVsaW1pdGVyc1swXTsKCQoJCXJldHVybiBsaW5lRGVsaW1pdGVyOwoJCQoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgZG9jdW1lbnQncyBwYXJ0aXRpb25lci4KCSAqIAoJICogQHNlZSBJRG9jdW1lbnRQYXJ0aXRpb25lcgoJICovCglwdWJsaWMgSURvY3VtZW50UGFydGl0aW9uZXIgZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcigpIHsKCQlyZXR1cm4gZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcihJRG9jdW1lbnRFeHRlbnNpb24zLkRFRkFVTFRfUEFSVElUSU9OSU5HKTsKCX0KCgoJcHVibGljIElEb2N1bWVudFBhcnRpdGlvbmVyIGdldERvY3VtZW50UGFydGl0aW9uZXIoU3RyaW5nIHBhcnRpdGlvbmluZykgewoKCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBkb2N1bWVudFBhcnRpdGlvbmVyID0gbnVsbDsKCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzICE9IG51bGwpIHsKCQkJZG9jdW1lbnRQYXJ0aXRpb25lciA9IChJRG9jdW1lbnRQYXJ0aXRpb25lcikgZkRvY3VtZW50UGFydGl0aW9uZXJzLmdldChwYXJ0aXRpb25pbmcpOwoJCX0KCQlyZXR1cm4gZG9jdW1lbnRQYXJ0aXRpb25lcjsKCX0KCglwdWJsaWMgRW5jb2RpbmdNZW1lbnRvIGdldEVuY29kaW5nTWVtZW50bygpIHsKCQlyZXR1cm4gZW5jb2RpbmdNZW1lbnRvOwoJfQoKCXB1YmxpYyBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGdldEZpcnN0U3RydWN0dXJlZERvY3VtZW50UmVnaW9uKCkgewoJCS8vIHNob3VsZCB3ZSB1cGRhdGUgY2FjaGVkTm9kZT8KCQkvLyBXZSBzaG91bGQgdG8ga2VlcCBjb25zaXN0ZW50IHBoaWxvc29waHkgb2YgcmVtZW1iZXJpbmcgbGFzdAoJCS8vIHJlcXVlc3RlZCBwb3NpdGlvbiwKCQkvLyBmb3IgZWZmaWNpZW5jeS4KCQlzZXRDYWNoZWREb2N1bWVudFJlZ2lvbihmaXJzdERvY3VtZW50UmVnaW9uKTsKCQlyZXR1cm4gZmlyc3REb2N1bWVudFJlZ2lvbjsKCX0KCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBnZXRMYXN0U3RydWN0dXJlZERvY3VtZW50UmVnaW9uKCkgewoJCS8vIHNob3VsZCB3ZSB1cGRhdGUgY2FjaGVkTm9kZT8KCQkvLyBXZSBzaG91bGQgdG8ga2VlcCBjb25zaXN0ZW50IHBoaWxvc29waHkgb2YgcmVtZW1iZXJpbmcgbGFzdAoJCS8vIHJlcXVlc3RlZCBwb3NpdGlvbiwKCQkvLyBmb3IgZWZmaWNpZW5jeS4KCQlzZXRDYWNoZWREb2N1bWVudFJlZ2lvbihsYXN0RG9jdW1lbnRSZWdpb24pOwoJCXJldHVybiBsYXN0RG9jdW1lbnRSZWdpb247Cgl9CgoJLyoKCSAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHBhcnRpdGlvbnMKCSAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCSAqLwoJcHVibGljIFN0cmluZ1tdIGdldExlZ2FsQ29udGVudFR5cGVzKCkgewoJCVN0cmluZ1tdIHJlc3VsdCA9IG51bGw7CgkJdHJ5IHsKCQkJcmVzdWx0ID0gZ2V0TGVnYWxDb250ZW50VHlwZXMoSVN0cnVjdHVyZWRQYXJ0aXRpb25pbmcuREVGQVVMVF9TVFJVQ1RVUkVEX1BBUlRJVElPTklORyk7CgkJfQoJCWNhdGNoIChCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24gZSkgewoJCQkvLyBpbXBvc3NpYmxlIGluIHRoaXMgY29udGV4dAoJCQl0aHJvdyBuZXcgRXJyb3IoZSk7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJcHVibGljIFN0cmluZ1tdIGdldExlZ2FsQ29udGVudFR5cGVzKFN0cmluZyBwYXJ0aXRpb25pbmcpIHRocm93cyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24gewoJCUlEb2N1bWVudFBhcnRpdGlvbmVyIHBhcnRpdGlvbmVyID0gZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcihwYXJ0aXRpb25pbmcpOwoJCWlmIChwYXJ0aXRpb25lciAhPSBudWxsKQoJCQlyZXR1cm4gcGFydGl0aW9uZXIuZ2V0TGVnYWxDb250ZW50VHlwZXMoKTsKCQlpZiAoSVN0cnVjdHVyZWRQYXJ0aXRpb25pbmcuREVGQVVMVF9TVFJVQ1RVUkVEX1BBUlRJVElPTklORy5lcXVhbHMocGFydGl0aW9uaW5nKSkKCQkJcmV0dXJuIG5ldyBTdHJpbmdbXXtERUZBVUxUX0NPTlRFTlRfVFlQRX07CgkJdGhyb3cgbmV3IEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbigpOwoJfQoKCS8qCgkgKiAtLS0tLS0tLS0tLS0tLS0tLS0gbGluZSBkZWxpbWl0ZXIgY29udmVyc2lvbgoJICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgkgKi8KCXB1YmxpYyBTdHJpbmdbXSBnZXRMZWdhbExpbmVEZWxpbWl0ZXJzKCkgewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TGVnYWxMaW5lRGVsaW1pdGVycygpOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjZ2V0TGVuZ3RoCgkgKi8KCXB1YmxpYyBpbnQgZ2V0TGVuZ3RoKCkgewoJCXJldHVybiBnZXRTdG9yZSgpLmdldExlbmd0aCgpOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLnRleHQuSVN0cnVjdHVyZWREb2N1bWVudCNnZXRMaW5lRGVsaW1pdGVyKCkKCSAqLwoJcHVibGljIFN0cmluZyBnZXRMaW5lRGVsaW1pdGVyKCkgewoJCXJldHVybiBnZXREZWZhdWx0TGluZURlbGltaXRlcigpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgbGluZSBkZWxpbWl0ZXIgb2YgdGhhdCBsaW5lCgkgKiAKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHRoZSBsaW5lIG51bWJlciBpcyBpbnZhbGlkIGluIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgU3RyaW5nIGdldExpbmVEZWxpbWl0ZXIoaW50IGxpbmUpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldExpbmVEZWxpbWl0ZXIobGluZSk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGEgZGVzY3JpcHRpb24gb2YgdGhlIHNwZWNpZmllZCBsaW5lLiBUaGUgbGluZSBpcyBkZXNjcmliZWQgYnkKCSAqIGl0cyBvZmZzZXQgYW5kIGl0cyBsZW5ndGggZXhjbHVkaW5nIHRoZSBsaW5lJ3MgZGVsaW1pdGVyLgoJICogCgkgKiBAcGFyYW0gbGluZQoJICogICAgICAgICAgICB0aGUgbGluZSBvZiBpbnRlcmVzdAoJICogQHJldHVybiBhIGxpbmUgZGVzY3JpcHRpb24KCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIHRoZSBsaW5lIG51bWJlciBpcyBpbnZhbGlkIGluIHRoaXMgZG9jdW1lbnQKCSAqLwoJcHVibGljIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSVJlZ2lvbiBnZXRMaW5lSW5mb3JtYXRpb24oaW50IGxpbmUpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldExpbmVJbmZvcm1hdGlvbihsaW5lKTsKCX0KCgkvKioKCSAqIFJldHVybnMgYSBkZXNjcmlwdGlvbiBvZiB0aGUgbGluZSBhdCB0aGUgZ2l2ZW4gb2Zmc2V0LiBUaGUgZGVzY3JpcHRpb24KCSAqIGNvbnRhaW5zIHRoZSBvZmZzZXQgYW5kIHRoZSBsZW5ndGggb2YgdGhlIGxpbmUgZXhjbHVkaW5nIHRoZSBsaW5lJ3MKCSAqIGRlbGltaXRlci4KCSAqIAoJICogQHBhcmFtIG9mZnNldAoJICogICAgICAgICAgICB0aGUgb2Zmc2V0IHdob3NlIGxpbmUgc2hvdWxkIGJlIGRlc2NyaWJlZAoJICogQHJldHVybiBhIHJlZ2lvbiBkZXNjcmliaW5nIHRoZSBsaW5lCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBpZiBvZmZzZXQgaXMgaW52YWxpZCBpbiB0aGlzIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklSZWdpb24gZ2V0TGluZUluZm9ybWF0aW9uT2ZPZmZzZXQoaW50IG9mZnNldCkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TGluZUluZm9ybWF0aW9uT2ZPZmZzZXQob2Zmc2V0KTsKCX0KCgkvKgoJICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBsaW5lIGluZm9ybWF0aW9uCgkgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoJICovCglwdWJsaWMgaW50IGdldExpbmVMZW5ndGgoaW50IGxpbmUpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldExpbmVMZW5ndGgobGluZSk7Cgl9CgoJLyoqCgkgKiBEZXRlcm1pbmVzIHRoZSBvZmZzZXQgb2YgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiB0aGUgZ2l2ZW4gbGluZS4KCSAqIAoJICogQHBhcmFtIGxpbmUKCSAqICAgICAgICAgICAgdGhlIGxpbmUgb2YgaW50ZXJlc3QKCSAqIEByZXR1cm4gdGhlIGRvY3VtZW50IG9mZnNldAoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgaWYgdGhlIGxpbmUgbnVtYmVyIGlzIGludmFsaWQgaW4gdGhpcyBkb2N1bWVudAoJICovCglwdWJsaWMgaW50IGdldExpbmVPZmZzZXQoaW50IGxpbmUpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldExpbmVPZmZzZXQobGluZSk7Cgl9CgoJcHVibGljIGludCBnZXRMaW5lT2ZPZmZzZXQoaW50IG9mZnNldCkgewoJCWludCByZXN1bHQgPSAtMTsKCQl0cnkgewoJCQlyZXN1bHQgPSBnZXRUcmFja2VyKCkuZ2V0TGluZU51bWJlck9mT2Zmc2V0KG9mZnNldCk7CgkJfQoJCWNhdGNoIChCYWRMb2NhdGlvbkV4Y2VwdGlvbiBlKSB7CgkJCWlmIChMb2dnZXIuREVCVUdfRE9DVU1FTlQpCgkJCQlMb2dnZXIubG9nKExvZ2dlci5JTkZPLCAiRGV2LiBQcm9ncmFtIEluZm8gT25seTogSVN0cnVjdHVyZWREb2N1bWVudDo6Z2V0TGluZU9mT2Zmc2V0OiBvZmZzZXQgb3V0IG9mIHJhbmdlLCB6ZXJvIGFzc3VtZWQuIG9mZnNldCA9ICIgKyBvZmZzZXQsIGUpOyAvLyROT04tTkxTLTEkIC8vJE5PTi1OTFMtMiQKCQkJcmVzdWx0ID0gMDsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIG51bWJlciBvZiBsaW5lcyBpbiB0aGlzIGRvY3VtZW50CgkgKiAKCSAqIEByZXR1cm4gdGhlIG51bWJlciBvZiBsaW5lcyBpbiB0aGlzIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBpbnQgZ2V0TnVtYmVyT2ZMaW5lcygpIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldE51bWJlck9mTGluZXMoKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIG51bWJlciBvZiBsaW5lcyB3aGljaCBhcmUgb2NjdXBpZWQgYnkgYSBnaXZlbiB0ZXh0IHJhbmdlLgoJICogCgkgKiBAcGFyYW0gb2Zmc2V0CgkgKiAgICAgICAgICAgIHRoZSBvZmZzZXQgb2YgdGhlIHNwZWNpZmllZCB0ZXh0IHJhbmdlCgkgKiBAcGFyYW0gbGVuZ3RoCgkgKiAgICAgICAgICAgIHRoZSBsZW5ndGggb2YgdGhlIHNwZWNpZmllZCB0ZXh0IHJhbmdlCgkgKiBAcmV0dXJuIHRoZSBudW1iZXIgb2YgbGluZXMgb2NjdXBpZWQgYnkgdGhlIHNwZWNpZmllZCByYW5nZQoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgaWYgc3BlY2lmaWVkIHJhbmdlIGlzIGludmFsaWQgaW4gdGhpcyB0cmFja2VyCgkgKi8KCXB1YmxpYyBpbnQgZ2V0TnVtYmVyT2ZMaW5lcyhpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXROdW1iZXJPZkxpbmVzKG9mZnNldCwgbGVuZ3RoKTsKCX0KCgkvKioKCSAqIFRoaXMgaXMgcHVibGljLCB0ZW1wb3JhcmlseSwgZm9yIHVzZSBieSB0YWcgbGliIGNsYXNzZXMuCgkgKi8KCXB1YmxpYyBSZWdpb25QYXJzZXIgZ2V0UGFyc2VyKCkgewoJCWlmIChmUGFyc2VyID09IG51bGwpIHsKCQkJdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiSVN0cnVjdHVyZWREb2N1bWVudDo6Z2V0UGFyc2VyLiBQYXJzZXIgbmVlZHMgdG8gYmUgc2V0IGJlZm9yZSB1c2UiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCQlyZXR1cm4gZlBhcnNlcjsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGRvY3VtZW50IHBhcnRpdGlvbiBpbiB3aGljaCB0aGUgcG9zaXRpb24gaXMgbG9jYXRlZC4gVGhlCgkgKiBwYXJ0aXRpb24gaXMgc3BlY2lmaWVkIGFzIHR5cGVkIHJlZ2lvbi4KCSAqLwoJcHVibGljIElUeXBlZFJlZ2lvbiBnZXRQYXJ0aXRpb24oaW50IG9mZnNldCkgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlJVHlwZWRSZWdpb24gcGFydGl0aW9uID0gbnVsbDsKCQl0cnkgewoJCQlwYXJ0aXRpb24gPSBnZXRQYXJ0aXRpb24oSVN0cnVjdHVyZWRQYXJ0aXRpb25pbmcuREVGQVVMVF9TVFJVQ1RVUkVEX1BBUlRJVElPTklORywgb2Zmc2V0LCBmYWxzZSk7CgkJfQoJCWNhdGNoIChCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24gZSkgewoJCQl0aHJvdyBuZXcgRXJyb3IoZSk7CgkJfQoJCWlmIChwYXJ0aXRpb24gPT0gbnVsbCkgewoJCQl0aHJvdyBuZXcgRXJyb3IoKTsKCQl9CgkJcmV0dXJuIHBhcnRpdGlvbjsKCX0KCgoJcHVibGljIElUeXBlZFJlZ2lvbiBnZXRQYXJ0aXRpb24oU3RyaW5nIHBhcnRpdGlvbmluZywgaW50IG9mZnNldCwgYm9vbGVhbiBwcmVmZXJPcGVuUGFydGl0aW9ucykgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uLCBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24gewoJCWlmICgoMCA+IG9mZnNldCkgfHwgKG9mZnNldCA+IGdldExlbmd0aCgpKSkKCQkJdGhyb3cgbmV3IEJhZExvY2F0aW9uRXhjZXB0aW9uKCk7CgkJSVR5cGVkUmVnaW9uIHJlc3VsdCA9IG51bGw7CgoJCUlEb2N1bWVudFBhcnRpdGlvbmVyIHBhcnRpdGlvbmVyID0gZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcihwYXJ0aXRpb25pbmcpOwoKCQlpZiAocGFydGl0aW9uZXIgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjIpIHsKCQkJcmVzdWx0ID0gKChJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjIpIHBhcnRpdGlvbmVyKS5nZXRQYXJ0aXRpb24ob2Zmc2V0LCBwcmVmZXJPcGVuUGFydGl0aW9ucyk7CgkJfQoJCWVsc2UgaWYgKHBhcnRpdGlvbmVyICE9IG51bGwpIHsKCQkJcmVzdWx0ID0gcGFydGl0aW9uZXIuZ2V0UGFydGl0aW9uKG9mZnNldCk7CgkJfQoJCWVsc2UgaWYgKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcuZXF1YWxzKHBhcnRpdGlvbmluZykpIHsKCQkJcmVzdWx0ID0gbmV3IFR5cGVkUmVnaW9uKDAsIGdldExlbmd0aCgpLCBERUZBVUxUX0NPTlRFTlRfVFlQRSk7CgkJfQoJCWVsc2UKCQkJdGhyb3cgbmV3IEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbigpOwoJCXJldHVybiByZXN1bHQ7Cgl9CgoKCXB1YmxpYyBTdHJpbmdbXSBnZXRQYXJ0aXRpb25pbmdzKCkgewoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgPT0gbnVsbCkKCQkJcmV0dXJuIG5ldyBTdHJpbmdbMF07CgkJU3RyaW5nW10gcGFydGl0aW9uaW5ncyA9IG5ldyBTdHJpbmdbZkRvY3VtZW50UGFydGl0aW9uZXJzLnNpemUoKV07CgkJZkRvY3VtZW50UGFydGl0aW9uZXJzLmtleVNldCgpLnRvQXJyYXkocGFydGl0aW9uaW5ncyk7CgkJcmV0dXJuIHBhcnRpdGlvbmluZ3M7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGFsbCBwb3NpdGlvbiBjYXRlZ29yaWVzIGFkZGVkIHRvIHRoaXMgZG9jdW1lbnQuCgkgKi8KCXB1YmxpYyBTdHJpbmdbXSBnZXRQb3NpdGlvbkNhdGVnb3JpZXMoKSB7CgkJcmV0dXJuIGdldFBvc2l0aW9uTWFuYWdlcigpLmdldFBvc2l0aW9uQ2F0ZWdvcmllcygpOwoJfQoKCS8qKgoJICogQHJldHVybiBSZXR1cm5zIHRoZSBwb3NpdGlvbk1hbmFnZXIuCgkgKi8KCXByaXZhdGUgR2VuZXJpY1Bvc2l0aW9uTWFuYWdlciBnZXRQb3NpdGlvbk1hbmFnZXIoKSB7CgkJaWYgKGZQb3NpdGlvbk1hbmFnZXIgPT0gbnVsbCkgewoJCQlmUG9zaXRpb25NYW5hZ2VyID0gbmV3IEdlbmVyaWNQb3NpdGlvbk1hbmFnZXIodGhpcyk7CgkJfQoJCXJldHVybiBmUG9zaXRpb25NYW5hZ2VyOwoJfQoKCS8qKgoJICogUmV0dXJucyBhbGwgUG9zaXRpb25zIG9mIHRoZSBnaXZlbiBwb3NpdGlvbiBjYXRlZ29yeS4KCSAqIAoJICogQGV4Y2VwdGlvbiBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiBjYXRlZ29yeSBpcyBub3QgZGVmaW5lZCBmb3IgdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBQb3NpdGlvbltdIGdldFBvc2l0aW9ucyhTdHJpbmcgY2F0ZWdvcnkpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5nZXRQb3NpdGlvbnMoY2F0ZWdvcnkpOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjZ2V0UG9zaXRpb25VcGRhdGVycwoJICovCglwdWJsaWMgSVBvc2l0aW9uVXBkYXRlcltdIGdldFBvc2l0aW9uVXBkYXRlcnMoKSB7CgkJcmV0dXJuIGdldFBvc2l0aW9uTWFuYWdlcigpLmdldFBvc2l0aW9uVXBkYXRlcnMoKTsKCX0KCgkvKioKCSAqIFRoaXMgbWV0aG9kIGNhbiByZXR1cm4gbnVsbCwgd2hpY2ggaXMgdGhlIGNhc2UgaWYgdGhlIG9mZnNldCBpcyBqdXN0CgkgKiBiZWZvcmUgb3IganVzdCBhZnRlciB0aGUgZXhpc3RpbmcgdGV4dC4gQ29tcGFyZSB3aXRoCgkgKiBnZXROb2RlQXRDaGFyYWN0ZXJPZmZzZXQuCgkgKi8KCXB1YmxpYyBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGdldFJlZ2lvbkF0Q2hhcmFjdGVyT2Zmc2V0KGludCBvZmZzZXQpIHsKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlc3VsdCA9IG51bGw7CgoJCS8vIEZJWE1FOiBuZWVkIHRvIHN5bmNoIG9uICdjYWNoZWRSZWdpb24nIChidXQgc2luY2UgdGhhdCdzIGEKCQkvLyBjb25zdGFudGx5IGNoYW5naW5nIG9iamVjdCwgd2UKCQkvLyBjYW4ndCwgc28gbmVlZCB0byBhZGQgYSAicmVnaW9uX2xvY2siIG9iamVjdCwgYW5kIHVzZSBpdCBoZXJlLCBhbmQKCQkvLyBpbiByZS1wYXJzZXIuCgkJLy8gT2gsIGFuZCBuZWVkIHRvIG1ha2Ugc3VyZSwgYWZ0ZXIgc3luY2gsIHRoYXQgdGhlIHJlZ2lvbiBpcyBub3QKCQkvLyBkZWxldGVkLCBhbmQgaWYgc28sIEkgZ3Vlc3MgZ28gYmFjawoJCS8vIHRvIHRoZSBiZWdpbm5pbmchCgoJCS8vIGNhY2hlZCBub2RlIGNhbiBiZSBudWxsIHdoZW4gZG9jdW1lbnQgaXMgZW1wdHkKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHBvdGVudGlhbENhY2hlZFJlZ2lvbiA9IGdldENhY2hlZERvY3VtZW50UmVnaW9uKCk7CgkJaWYgKHBvdGVudGlhbENhY2hlZFJlZ2lvbiAhPSBudWxsKSB7CgoJCQkvLyAKCgkJCS8vIGlmIHdlIGFscmVhZHkgaGF2ZSB0aGUgcmlnaHQgbm9kZSwgcmV0dXJuIHRoYXQuCgkJCWlmIChwb3RlbnRpYWxDYWNoZWRSZWdpb24uY29udGFpbnNPZmZzZXQob2Zmc2V0KSkgewoJCQkJcmVzdWx0ID0gcG90ZW50aWFsQ2FjaGVkUmVnaW9uOwoJCQl9CgkJCWVsc2UgewoJCQkJLy8gZmlyc3QsIGZpbmQgb3V0IHdoYXQgZGlyZWN0aW9uIHRvIGdvLCByZWxhdGl2ZSB0bwoJCQkJLy8gY2FjaGVkTm9kZS4KCQkJCS8vIG5lZ2F0aXZlIG1lYW5zICJ0b3dhcmRzIHRoZSBmcm9udCIgb2YgdGhlIGZpbGUsCgkJCQkvLyBwb3N0aXRpdmUKCQkJCS8vIG1lYW5zCgkJCQkvLyB0b3dhcmRzIHRoZSBlbmQuCgkJCQlpbnQgZGlyZWN0aW9uID0gb2Zmc2V0IC0gcG90ZW50aWFsQ2FjaGVkUmVnaW9uLmdldFN0YXJ0KCk7CgkJCQlpZiAoZGlyZWN0aW9uIDwgMCkgewoJCQkJCS8vIHNlYXJjaCB0b3dhcmRzIGJlZ2lubmluZwoJCQkJCXdoaWxlICghcG90ZW50aWFsQ2FjaGVkUmVnaW9uLmNvbnRhaW5zT2Zmc2V0KG9mZnNldCkpIHsKCQkJCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiB0ZW1wTm9kZSA9IHBvdGVudGlhbENhY2hlZFJlZ2lvbi5nZXRQcmV2aW91cygpOwoJCQkJCQlpZiAodGVtcE5vZGUgPT0gbnVsbCkgewoJCQkJCQkJYnJlYWs7CgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQlwb3RlbnRpYWxDYWNoZWRSZWdpb24gPSB0ZW1wTm9kZTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJCWVsc2UgewoJCQkJCS8vIHNlYXJjaCB0b3dhcmRzIGVuZAoJCQkJCS8vIFRoZXJlIGlzIGEgbGVnaXRhbWF0IGNvbmRpdGlvbiB3aGVyZSB0aGUKCQkJCQkvLyBvZmZzZXQgd2lsbCBub3QgYmUgY29udGFpbmVkIGluIGFueSBub2RlLAoJCQkJCS8vIHdoaWNoIGlzIGlmIHRoZSBvZmZzZXQgaXMganVzdCBwYXN0IHRoZSBsYXN0CgkJCQkJLy8gY2hhcmFjdGVyIG9mIHRleHQuCgkJCQkJLy8gQW5kLCB3ZSBtdXN0IGdhdXJkIGFnYWluc3Qgc2V0dGluZyBjYWNoZWROb2RlIHRvCgkJCQkJLy8gbnVsbCEKCQkJCQl3aGlsZSAoIXBvdGVudGlhbENhY2hlZFJlZ2lvbi5jb250YWluc09mZnNldChvZmZzZXQpKSB7CgkJCQkJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gdGVtcE5vZGUgPSBwb3RlbnRpYWxDYWNoZWRSZWdpb24uZ2V0TmV4dCgpOwoJCQkJCQlpZiAodGVtcE5vZGUgPT0gbnVsbCkKCQkJCQkJCWJyZWFrOwoJCQkJCQllbHNlCgkJCQkJCQlwb3RlbnRpYWxDYWNoZWRSZWdpb24gPSB0ZW1wTm9kZTsKCQkJCQl9CgkJCQl9CgkJCX0KCQkJcmVzdWx0ID0gcG90ZW50aWFsQ2FjaGVkUmVnaW9uOwoJCX0KCQkvLyBqdXN0IHRvIGJlIGRvdWJseSBzdXJlIHdlIG5ldmVyIGFzc2lnbiBudWxsIHRvIGFuIGFscmVhZHkgdmFsaWQKCQkvLyBjYWNoZWRSZWdpb24uCgkJLy8gSSBiZWxpZXZlIGFueSB0aW1lICdyZXN1bHQnIGlzIG51bGwgYXQgdGhpcyBwb2ludCwgdGhhdCBqdXN0IG1lYW5zCgkJLy8gd2UgaGF2ZSBhbgoJCS8vIGVtcHR5IGRvY3VtZW50LCBhbmQgdGhlIGNhY2hlZFJlZ2lvbiBpcyBhbHJlYWR5IG51bGwsIGJ1dCB3ZSBjaGVjawoJCS8vIGFuZCBwcmludAoJCS8vIHdhcm5pbmcsIGp1c3Qgc28gZHVyaW5nIGRldmVsb3BtZW50IHdlIGJlIHN1cmUgd2UgbmV2ZXIgYWNjaWRlbnRseQoJCS8vIGJyZWFrIHRoaXMgYXNzdW1wdGlvbi4KCQlpZiAocmVzdWx0ICE9IG51bGwpCgkJCXNldENhY2hlZERvY3VtZW50UmVnaW9uKHJlc3VsdCk7CgkJZWxzZSBpZiAoZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKSAhPSBudWxsKSB7CgkJCXRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlByb2dyYW0gRXJyb3I6IG5vIHJlZ2lvbiBjb3VsZCBiZSBmb3VuZCB0byBjYWNoZSwgYnV0IGNhY2hlIHdhcyBub24gbnVsbC4gSW5kaWNhdGVzIGNvcnJ1cHRlZCBtb2RlbCBvciByZWdpb24gbGlzdCIpOyAvLyROT04tTkxTLTEkCgkJfQoKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXB1YmxpYyBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uTGlzdCBnZXRSZWdpb25MaXN0KCkgewoJCUNvcmVOb2RlTGlzdCByZXN1bHQgPSBudWxsOwoJCWlmIChnZXRDYWNoZWREb2N1bWVudFJlZ2lvbigpID09IG51bGwpCgkJCXJlc3VsdCA9IG5ldyBDb3JlTm9kZUxpc3QobnVsbCk7CgkJZWxzZQoJCQlyZXN1bHQgPSBuZXcgQ29yZU5vZGVMaXN0KGdldEZpcnN0U3RydWN0dXJlZERvY3VtZW50UmVnaW9uKCkpOwoKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbltdIGdldFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnMoKSB7CgkJcmV0dXJuIGdldFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnMoMCwgZ2V0TGVuZ3RoKCkpOwoJfQoKCS8qKgoJICogPHA+CgkgKiBJbiB0aGUgY2FzZSBvZiAwIGxlbmd0aCwgdGhlIDxjb2RlPklTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb248L2NvZGU+CgkgKiBhdCB0aGUgY2hhcmFjdGVyIG9mZnNldCBpcyByZXR1cmVuZWQuIEluIG90aGVyIHdvcmRzLCB0aGUgcmVnaW9uIHRvIHRoZQoJICogcmlnaHQgb2YgdGhlIGNhcmV0IGlzIHJldHVybmVkLiBleGNlcHQgZm9yIGF0IHRoZSBlbmQgb2YgdGhlIGRvY3VtZW50LAoJICogdGhlbiB0aGUgbGFzdCByZWdpb24gaXMgcmV0dXJuZWQuCgkgKiA8L3A+CgkgKiA8cD4KCSAqIE90aGVyd2lzZSBhbGwgdGhlIHJlZ2lvbnMgImluYmV0d2VlbiIgdGhlIGluZGljYXRlZCByYW5nZSBhcmUgcmV0dXJuZWQsCgkgKiBpbmNsdWRpbmcgdGhlIHJlZ2lvbnMgd2hpY2ggb3ZlcmxhcCB0aGUgcmVnaW9uLgoJICogPC9wPgoJICogCgkgKiA8YnI+CgkgKiBlZy4KCSAqIDxwPgoJICogPGJyPgoJICogZWcuCgkgKiAKCSAqIDxwcmU+CgkgKiAgICAgICAgICAgICAgICAgICAgICAgICZsdDtodG1sJmd0O1smbHQ7aGVhZCZndDsmbHQ7L2hlYWQmZ3Q7XSZsdDsvaHRtbCZndDsgcmV0dXJucyAmbHQ7aGVhZCZndDssJmx0Oy9oZWFkJmd0OwoJICogPC9wcmU+CgkgKiAgICA8cHJlPgoJICogICAgICAgICAgICAgICAgICAgICAgICAmbHQ7aHRbbWwmZ3Q7Jmx0O2hlYWQmZ3Q7Jmx0Oy9oZV1hZCZndDsmbHQ7L2h0bWwmZ3Q7IHJldHVybnMgJmx0O2h0bWwmZ3Q7LCZsdDtoZWFkJmd0OywmbHQ7L2hlYWQmZ3Q7CgkgKiA8L3ByZT4KCSAqIAoJICogPHByZT4KCSAqICAgICAgICAgICAgICAgICAgICAgICAgICAmbHQ7aHRtbCZndDtbJmx0O2hlYWQmZ3Q7Jmx0Oy9oZWFkJmd0O10mbHQ7L2h0bWwmZ3Q7IHJldHVybnMgJmx0O2hlYWQmZ3Q7LCZsdDsvaGVhZCZndDsKCSAqIDwvcHJlPgoJICogICAgPHByZT4KCSAqICAgICAgICAgICAgICAgICAgICAgICAgICAmbHQ7aHRbbWwmZ3Q7Jmx0O2hlYWQmZ3Q7Jmx0Oy9oZV1hZCZndDsmbHQ7L2h0bWwmZ3Q7IHJldHVybnMgJmx0O2h0bWwmZ3Q7LCZsdDtoZWFkJmd0OywmbHQ7L2hlYWQmZ3Q7CgkgKiA8L3ByZT4KCSAqIAoJICogPC9wPgoJICovCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbltdIGdldFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnMoaW50IHN0YXJ0LCBpbnQgbGVuZ3RoKSB7CgoJCWlmIChsZW5ndGggPCAwKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJjYW4ndCBoYXZlIG5lZ2F0aXZlIGxlbmd0aCIpOyAvLyROT04tTkxTLTEkCgoJCS8vIHRoaXMgd2lsbCBtYWtlIHRoZSByaWdodCBlZGdlIG9mIHRoZSByYW5nZSBwb2ludCBpbnRvIHRoZSBzZWxlY3Rpb24KCQkvLyBlZy4gPGh0bWw+WzxoZWFkPjwvaGVhZD5dPC9odG1sPgoJCS8vIHdpbGwgcmV0dXJuIDxoZWFkPiw8L2hlYWQ+IGluc3RlYWQgb2YgPGhlYWQ+LDwvaGVhZD4sPC9odG1sPgoJCWlmIChsZW5ndGggPiAwKQoJCQlsZW5ndGgtLTsKCgkJTGlzdCByZXN1bHRzID0gbmV3IEFycmF5TGlzdCgpOwoKCQkvLyBzdGFydCB0aHJlYWQgc2FmZSBibG9jawoJCXRyeSB7CgkJCWFjcXVpcmVMb2NrKCk7CgoJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGN1cnJlbnRSZWdpb24gPSBnZXRSZWdpb25BdENoYXJhY3Rlck9mZnNldChzdGFydCk7CgkJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZW5kUmVnaW9uID0gZ2V0UmVnaW9uQXRDaGFyYWN0ZXJPZmZzZXQoc3RhcnQgKyBsZW5ndGgpOwoJCQl3aGlsZSAoY3VycmVudFJlZ2lvbiAhPSBlbmRSZWdpb24gJiYgY3VycmVudFJlZ2lvbiAhPSBudWxsKSB7CgkJCQlyZXN1bHRzLmFkZChjdXJyZW50UmVnaW9uKTsKCQkJCWN1cnJlbnRSZWdpb24gPSBjdXJyZW50UmVnaW9uLmdldE5leHQoKTsKCQkJfQoJCQkvLyBuZWVkIHRvIGFkZCB0aGF0IGxhc3QgZW5kIHJlZ2lvbgoJCQkvLyBjYW4gYmUgbnVsbCBpbiB0aGUgY2FzZSBvZiBhbiBlbXB0eSBkb2N1bWVudAoJCQlpZiAoZW5kUmVnaW9uICE9IG51bGwpCgkJCQlyZXN1bHRzLmFkZChlbmRSZWdpb24pOwoJCX0KCQlmaW5hbGx5IHsKCQkJcmVsZWFzZUxvY2soKTsKCQl9CgkJLy8gZW5kIHRocmVhZCBzYWZlIGJsb2NrCgoJCXJldHVybiAoSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbltdKSByZXN1bHRzLnRvQXJyYXkobmV3IElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25bcmVzdWx0cy5zaXplKCldKTsKCX0KCgkvKioKCSAqIHdhcyBtYWRlIHB1YmxpYyBmb3IgZWFzaWVyIHRlc3RpbmcuIE5vcm1hbGx5IHNob3VsZCBuZXZlciBiZSB1c2VkIGJ5CgkgKiBjbGllbnQgY29kZXMuCgkgKi8KCXB1YmxpYyBJU3RydWN0dXJlZFRleHRSZVBhcnNlciBnZXRSZVBhcnNlcigpIHsKCQlpZiAoZlJlUGFyc2VyID09IG51bGwpIHsKCQkJZlJlUGFyc2VyID0gbmV3IFN0cnVjdHVyZWREb2N1bWVudFJlUGFyc2VyKCk7CgkJCWZSZVBhcnNlci5zZXRTdHJ1Y3R1cmVkRG9jdW1lbnQodGhpcyk7CgkJfQoJCXJldHVybiBmUmVQYXJzZXI7Cgl9CgoJcHJpdmF0ZSBJVGV4dFN0b3JlIGdldFN0b3JlKCkgewoJCXJldHVybiBmU3RvcmU7Cgl9CgoJcHVibGljIFN0cmluZyBnZXRUZXh0KCkgewoJCVN0cmluZyByZXN1bHQgPSBnZXQoKTsKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgZG9jdW1lbnQncyBsaW5lIHRyYWNrZXIuIEFzc3VtZXMgdGhhdCB0aGUgZG9jdW1lbnQgaGFzIGJlZW4KCSAqIGluaXRpYWxpemVkIHdpdGggYSBsaW5lIHRyYWNrZXIuCgkgKiAKCSAqIEByZXR1cm4gdGhlIGRvY3VtZW50J3MgbGluZSB0cmFja2VyCgkgKi8KCXByaXZhdGUgSUxpbmVUcmFja2VyIGdldFRyYWNrZXIoKSB7CgkJQXNzZXJ0LmlzTm90TnVsbChmVHJhY2tlcik7CgkJcmV0dXJuIGZUcmFja2VyOwoJfQoKCXB1YmxpYyBJU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlciBnZXRVbmRvTWFuYWdlcigpIHsKCQlpZiAoZlVuZG9NYW5hZ2VyID09IG51bGwpIHsKCQkJZlVuZG9NYW5hZ2VyID0gbmV3IFN0cnVjdHVyZWRUZXh0VW5kb01hbmFnZXIoKTsKCQl9CgkJcmV0dXJuIGZVbmRvTWFuYWdlcjsKCX0KCgl2b2lkIGluaXRpYWxpemVGaXJzdEFuZExhc3REb2N1bWVudFJlZ2lvbigpIHsKCQkvLyBjYWNoZWQgTm9kZSBtdXN0IGFsc28gYmUgZmlyc3QsIGF0IHRoZSBpbml0aWFsIHBvaW50LiBPbmx5CgkJLy8gdmFsaWQKCQkvLyB0byBjYWxsIHRoaXMgbWV0aG9kIHJpZ2h0IGFmdGVyIHRoZSBmaXJzdCBwYXJzZS4KCQkvLyAKCQkvLyB3aGVuIHN0YXJ0aW5nIGFmcmVzaCwgb3VyIGNhY2hlZE5vZGUgc2hvdWxkIGJlIG91ciBmaXJzdE5vZGUsCgkJLy8gc28gYmUgc3VyZSB0byBpbml0aWFsaXplIHRoZSBmaXJzdE5vZGUKCQlmaXJzdERvY3VtZW50UmVnaW9uID0gZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKTsKCQkvLyBiZSBzdXJlIHRvIHVzZSAnZ2V0TmV4dCcgZm9yIHRoaXMgaW5pdGlhbCBmaW5kaW5nIG9mIHRoZSBsYXN0CgkJLy8gbm9kZSwKCQkvLyBzaW5jZSB0aGUgaW1wbGVtZW50YXRpb24gb2Ygbm9kZS5nZXRMYXN0Tm9kZSBtYXkgc2ltcGx5IGNhbGwKCQkvLyBzdHJ1Y3R1cmVkRG9jdW1lbnQuZ2V0TGFzdFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiEKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGFOb2RlID0gZmlyc3REb2N1bWVudFJlZ2lvbjsKCQlpZiAoYU5vZGUgPT0gbnVsbCkgewoJCQkvLyBkZWZlY3QgMjU0NjA3OiB0byBoYW5kbGUgZW1wdHkgZG9jdW1lbnRzIHJpZ2h0LCBpZgoJCQkvLyBmaXJzdG5vZGUgaXMKCQkJLy8gbnVsbCwgbWFrZSBzdXJlIGxhc3Qgbm9kZSBpcyBudWxsIHRvbwoJCQlsYXN0RG9jdW1lbnRSZWdpb24gPSBudWxsOwoJCX0KCQllbHNlIHsKCQkJd2hpbGUgKGFOb2RlICE9IG51bGwpIHsKCQkJCWxhc3REb2N1bWVudFJlZ2lvbiA9IGFOb2RlOwoJCQkJYU5vZGUgPSBhTm9kZS5nZXROZXh0KCk7CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNpbnNlcnRQb3NpdGlvblVwZGF0ZXIKCSAqLwoJcHVibGljIHZvaWQgaW5zZXJ0UG9zaXRpb25VcGRhdGVyKElQb3NpdGlvblVwZGF0ZXIgdXBkYXRlciwgaW50IGluZGV4KSB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkuaW5zZXJ0UG9zaXRpb25VcGRhdGVyKHVwZGF0ZXIsIGluZGV4KTsKCX0KCglwcml2YXRlIHZvaWQgaW50ZXJuYWxfYWRkUG9zaXRpb25DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnkpIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5hZGRQb3NpdGlvbkNhdGVnb3J5KGNhdGVnb3J5KTsKCX0KCglwcml2YXRlIHZvaWQgaW50ZXJuYWxfYWRkUG9zaXRpb25VcGRhdGVyKElQb3NpdGlvblVwZGF0ZXIgdXBkYXRlcikgewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLmFkZFBvc2l0aW9uVXBkYXRlcih1cGRhdGVyKTsKCX0KCglwcml2YXRlIHZvaWQgaW50ZXJuYWxfc2V0UGFyc2VyKFJlZ2lvblBhcnNlciBuZXdQYXJzZXIpIHsKCQlmUGFyc2VyID0gbmV3UGFyc2VyOwoJfQoKCVN0cmluZyBpbnRlcm5hbEdldChpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJU3RyaW5nIHJlc3VsdCA9IG51bGw7CgkJLy8gaW50IG15TGVuZ3RoID0gZ2V0TGVuZ3RoKCk7CgkJLy8gaWYgKCgwID4gb2Zmc2V0KSB8fCAoMCA+IGxlbmd0aCkgfHwgKG9mZnNldCArIGxlbmd0aCA+IG15TGVuZ3RoKSkKCQkvLyB0aHJvdyBuZXcgQmFkTG9jYXRpb25FeGNlcHRpb24oKTsKCQlyZXN1bHQgPSBnZXRTdG9yZSgpLmdldChvZmZzZXQsIGxlbmd0aCk7CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIEBwYXJhbSByZXF1ZXN0ZXIKCSAqIEBwYXJhbSBzdGFydAoJICogQHBhcmFtIHJlcGxhY2VtZW50TGVuZ3RoCgkgKiBAcGFyYW0gY2hhbmdlcwoJICogQHBhcmFtIG1vZGlmaWNhdGlvblN0YW1wCgkgKiBAcGFyYW0gaWdub3JlUmVhZE9ubHlTZXR0aW5ncwoJICogQHJldHVybgoJICovCglwcml2YXRlIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IGludGVybmFsUmVwbGFjZVRleHQoT2JqZWN0IHJlcXVlc3RlciwgaW50IHN0YXJ0LCBpbnQgcmVwbGFjZW1lbnRMZW5ndGgsIFN0cmluZyBjaGFuZ2VzLCBsb25nIG1vZGlmaWNhdGlvblN0YW1wLCBib29sZWFuIGlnbm9yZVJlYWRPbmx5U2V0dGluZ3MpIHsKCQlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCByZXN1bHQgPSBudWxsOwoKCQlzdG9wUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCQlpZiAoY2hhbmdlcyA9PSBudWxsKQoJCQljaGFuZ2VzID0gIiI7IC8vJE5PTi1OTFMtMSQKCQkvLyAKCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpCgkJCVN5c3RlbS5vdXQucHJpbnRsbihnZXRDbGFzcygpLmdldE5hbWUoKSArICI6OnJlcGxhY2VUZXh0KCIgKyBzdGFydCArICIsIiArIHJlcGxhY2VtZW50TGVuZ3RoICsgIiwiICsgY2hhbmdlcyArICIpIik7IC8vJE5PTi1OTFMtNCQvLyROT04tTkxTLTMkLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQlpZiAoRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRPbmx5IHx8IERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0UmF3U3RydWN0dXJlZERvY3VtZW50T25seSkgewoJCQlzdGFydFN0cmVhbVRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQl9CgkJdHJ5IHsKCQkJLy8gTm90ZTogZXZlbnQgbXVzdCBiZSBjb21wdXRlZCBiZWZvcmUgJ2ZpcmUnIG1ldGhvZCBjYWxsZWQKCQkJZkRvY3VtZW50RXZlbnQgPSBuZXcgRG9jdW1lbnRFdmVudCh0aGlzLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgsIGNoYW5nZXMpOwoJCQlmaXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlZCgpOwoKCQkJdHJ5IHsKCQkJCWFjcXVpcmVMb2NrKCk7CgoJCQkJaWYgKCFpZ25vcmVSZWFkT25seVNldHRpbmdzICYmIChjb250YWluc1JlYWRPbmx5KHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCkpKSB7CgkJCQkJTm9DaGFuZ2VFdmVudCBub0NoYW5nZUV2ZW50ID0gbmV3IE5vQ2hhbmdlRXZlbnQodGhpcywgcmVxdWVzdGVyLCBjaGFuZ2VzLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgpOwoJCQkJCW5vQ2hhbmdlRXZlbnQucmVhc29uID0gTm9DaGFuZ2VFdmVudC5SRUFEX09OTFlfU1RBVEVfQ0hBTkdFOwoJCQkJCXJlc3VsdCA9IG5vQ2hhbmdlRXZlbnQ7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlyZXN1bHQgPSB1cGRhdGVNb2RlbChyZXF1ZXN0ZXIsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCwgY2hhbmdlcyk7CgkJCQl9CgkJCX0KCQkJZmluYWxseSB7CgkJCQlyZWxlYXNlTG9jaygpOwoJCQl9CgoKCQkJaWYgKERlYnVnLnBlcmZUZXN0UmF3U3RydWN0dXJlZERvY3VtZW50T25seSB8fCBEZWJ1Zy5wZXJmVGVzdCkgewoJCQkJbG9uZyBzdG9wU3RyZWFtVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IFRpbWUgZm9yIElTdHJ1Y3R1cmVkRG9jdW1lbnQgcmF3IHJlcGxhY2VUZXh0OiAiICsgKHN0b3BTdHJlYW1UaW1lIC0gc3RhcnRTdHJlYW1UaW1lKSk7IC8vJE5PTi1OTFMtMSQKCQkJfQoJCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpIHsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiZXZlbnQgdHlwZSByZXR1cm5lZCBieSByZXBsYWNlVGV4dFdpdGhOb0RlYnVnZ2luZ1RocmVhZDogIiArIHJlc3VsdCk7IC8vJE5PTi1OTFMtMSQKCQkJfQoJCX0KCQlmaW5hbGx5IHsKCQkJLy8gRlVUVVJFX1RPX0RPOiBpbXBsZW1lbnQgY2FsbGJhY2sgbWVjaGFuaXNtPyB0byBhdm9pZCBpbnN0YW5jZW9mCgkJCS8vIGFuZCBjYXN0aW5nCgkJCS8vIGZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCBtdXN0IGJlIGNhbGxlZCBpbiBvcmRlciB0byBlbmQKCQkJLy8gZG9jdW1lbnRBYm91dFRvQmVDaGFuZ2VkIHN0YXRlCgoKCQkJLy8gaW5jcmVtZW50IG1vZGlmaWNhdGlvbiBzdGFtcCBpZiBtb2RpZmljYXRpb25zIHdlcmUgbWFkZQoJCQlpZiAocmVzdWx0ICE9IG51bGwgJiYgIShyZXN1bHQgaW5zdGFuY2VvZiBOb0NoYW5nZUV2ZW50KSkgewoJCQkJZk1vZGlmaWNhdGlvblN0YW1wPSBtb2RpZmljYXRpb25TdGFtcDsKCQkJCWZOZXh0TW9kaWZpY2F0aW9uU3RhbXA9IE1hdGgubWF4KGZNb2RpZmljYXRpb25TdGFtcCwgZk5leHRNb2RpZmljYXRpb25TdGFtcCk7CgkJCQlmRG9jdW1lbnRFdmVudC5mTW9kaWZpY2F0aW9uU3RhbXAgPSBmTW9kaWZpY2F0aW9uU3RhbXA7CgkJCX0KCQkJCQoJCQlpZiAocmVzdWx0ID09IG51bGwpIHsKCQkJCS8vIHJlc3VsdCBzaG91bGQgbm90IGJlIG51bGwsIGJ1dCBpZiBhbiBleGNlcHRpb24gd2FzIHRocm93biwKCQkJCS8vIGl0IHdpbGwgYmUKCQkJCS8vIHNvIHNlbmQgYSBub0NoYW5nZUV2ZW50IGFuZCBsb2cgdGhlIHByb2JsZW0KCQkJCU5vQ2hhbmdlRXZlbnQgbm9DaGFuZ2VFdmVudCA9IG5ldyBOb0NoYW5nZUV2ZW50KHRoaXMsIHJlcXVlc3RlciwgY2hhbmdlcywgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoKTsKCQkJCW5vQ2hhbmdlRXZlbnQucmVhc29uID0gTm9DaGFuZ2VFdmVudC5OT19FVkVOVDsKCQkJCWZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChub0NoYW5nZUV2ZW50KTsKCQkJCUxvZ2dlci5sb2coTG9nZ2VyLkVSUk9SLCAiUHJvZ3JhbSBFcnJvcjogaW52YWxpZCBzdHJ1Y3R1cmVkIGRvY3VtZW50IGV2ZW50Iik7IC8vJE5PTi1OTFMtMSQKCQkJfQoJCQllbHNlIHsKCQkJCWlmIChyZXN1bHQgaW5zdGFuY2VvZiBSZWdpb25DaGFuZ2VkRXZlbnQpIHsKCQkJCQlmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoKFJlZ2lvbkNoYW5nZWRFdmVudCkgcmVzdWx0KTsKCQkJCX0KCQkJCWVsc2UgewoJCQkJCWlmIChyZXN1bHQgaW5zdGFuY2VvZiBSZWdpb25zUmVwbGFjZWRFdmVudCkgewoJCQkJCQlmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoKFJlZ2lvbnNSZXBsYWNlZEV2ZW50KSByZXN1bHQpOwoJCQkJCX0KCQkJCQllbHNlIHsKCQkJCQkJaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50KSB7CgkJCQkJCQkvLyBwcm9iYWJseSBtb3JlIGVmZmljaWVudCB0byBtYXJrIG9sZCByZWdpb25zIGFzCgkJCQkJCQkvLyAnZGVsZXRlZCcgYXQgdGhlIHRpbWUKCQkJCQkJCS8vIHRoYXQgYXJlIGRldGVybWluZWQgdG8gYmUgZGVsZXRlZCwgYnV0IEknbGwgZG8KCQkJCQkJCS8vIGhlcmUKCQkJCQkJCS8vIGluIHRoZW4gY2VudHJhbCBzcG90CgkJCQkJCQkvLyBmb3IgcHJvZ3JhbW1pbmcgZWFzZS4KCQkJCQkJCXVwZGF0ZURlbGV0ZWRGaWVsZHMoKFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50KSByZXN1bHQpOwoJCQkJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KChTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCkgcmVzdWx0KTsKCQkJCQkJfQoJCQkJCQllbHNlIHsKCQkJCQkJCWlmIChyZXN1bHQgaW5zdGFuY2VvZiBOb0NoYW5nZUV2ZW50KSB7CgkJCQkJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KChOb0NoYW5nZUV2ZW50KSByZXN1bHQpOwoJCQkJCQkJfQoJCQkJCQkJZWxzZSB7CgkJCQkJCQkJLy8gaWYgaGVyZSwgdGhpcyBtZWFucyBhIG5ldyBldmVudCB3YXMgY3JlYXRlZAoJCQkJCQkJCS8vIGFuZCBub3QgaGFuZGxlZCBoZXJlCgkJCQkJCQkJLy8ganVzdCBzZW5kIGEgbm8gZXZlbnQgdW50aWwgdGhpcyBpc3N1ZSBpcwoJCQkJCQkJCS8vIHJlc29sdmVkLgoJCQkJCQkJCU5vQ2hhbmdlRXZlbnQgbm9DaGFuZ2VFdmVudCA9IG5ldyBOb0NoYW5nZUV2ZW50KHRoaXMsIHJlcXVlc3RlciwgY2hhbmdlcywgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoKTsKCQkJCQkJCQlub0NoYW5nZUV2ZW50LnJlYXNvbiA9IE5vQ2hhbmdlRXZlbnQuTk9fRVZFTlQ7CgkJCQkJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KG5vQ2hhbmdlRXZlbnQpOwoJCQkJCQkJCUxvZ2dlci5sb2coTG9nZ2VyLklORk8sICJQcm9ncmFtIEVycm9yOiB1bmV4cGVjdGVkIHN0cnVjdHVyZWQgZG9jdW1lbnQgZXZlbnQ6ICIgKyByZXN1bHQpOyAvLyROT04tTkxTLTEkCgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCgkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudE9ubHkpIHsKCQkJCWxvbmcgc3RvcFN0cmVhbVRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBUb3RhbCBUaW1lIGZvciBJU3RydWN0dXJlZERvY3VtZW50IGV2ZW50IHNpZ25hbGluZy9wcm9jZXNzaW5nIGluIHJlcGxhY2VUZXh0OiAiICsgKHN0b3BTdHJlYW1UaW1lIC0gc3RhcnRTdHJlYW1UaW1lKSk7IC8vJE5PTi1OTFMtMSQKCQkJfQoJCQlyZXN1bWVQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgamF2YS5sYW5nLkNoYXJTZXF1ZW5jZSNsZW5ndGgoKQoJICovCglwdWJsaWMgaW50IGxlbmd0aCgpIHsKCgkJcmV0dXJuIGdldExlbmd0aCgpOwoJfQoJCglwdWJsaWMgdm9pZCBtYWtlUmVhZE9ubHkoaW50IHN0YXJ0T2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJbWFrZVJlYWRPbmx5KHN0YXJ0T2Zmc2V0LCBsZW5ndGgsIGZhbHNlLCBmYWxzZSk7Cgl9CgoJcHVibGljIHZvaWQgbWFrZVJlYWRPbmx5KGludCBzdGFydE9mZnNldCwgaW50IGxlbmd0aCwgYm9vbGVhbiBjYW5JbnNlcnRCZWZvcmUsIGJvb2xlYW4gY2FuSW5zZXJ0QWZ0ZXIpIHsJCgkJLy8gZG9lc24ndCBtYWtlIHNlbnNlIHRvIGhhdmUgYSByZWFkb25seSByZWdpb24gb2YgMCBsZW5ndGgsCgkJLy8gc28gd2UnbGwgaWdub3JlIHRob3NlIHJlcXVlc3RzCgkJaWYgKGxlbmd0aCA8PSAwKQoJCQlyZXR1cm47CgkJU3RyaW5nIGFmZmVjdGVkVGV4dCA9IHRoaXMuZ2V0KHN0YXJ0T2Zmc2V0LCBsZW5ndGgpOwoJCS8vIGEgZG9jdW1lbnQgZXZlbnQgZm9yICJyZWFkIG9ubHkiIGNoYW5nZSAuLi4gbXVzdAoJCS8vIGJlIGZvbGxvd2VkIGJ5ICJubyBjaGFuZ2UiIHN0cnVjdHVyZWREb2N1bWVudCBldmVudAoJCS8vIGZEb2N1bWVudEV2ZW50ID0gbmV3IERvY3VtZW50RXZlbnQodGhpcywgc3RhcnRPZmZzZXQsIGxlbmd0aCwKCQkvLyBhZmZlY3RlZFRleHQpOwoJCWZpcmVSZWFkT25seUFib3V0VG9CZUNoYW5nZWQoKTsKCQkvLyBpZiAoY29udGFpbnNSZWFkT25seShzdGFydE9mZnNldCwgbGVuZ3RoKSkgewoJCS8vIGFkanVzdFJlYWRPbmx5UmVnaW9ucyhzdGFydE9mZnNldCwgbGVuZ3RoKTsKCQkvLyB9IGVsc2UgewoJCS8vIHdlIGNhbiBibGluZGx5IGFkZCBjYXRlZ29yeSwgc2luY2Ugbm8gaGFybSBkb25lIGlmIGFscmVhZHkKCQkvLyBleGlzdHMuCgkJYWRkUG9zaXRpb25DYXRlZ29yeShSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSk7CgkJUG9zaXRpb24gbmV3UG9zaXRpb24gPSBuZXcgUmVhZE9ubHlQb3NpdGlvbihzdGFydE9mZnNldCwgbGVuZ3RoLCBjYW5JbnNlcnRCZWZvcmUpOwoJCXRyeSB7CgkJCWFkZFBvc2l0aW9uKFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZLCBuZXdQb3NpdGlvbik7CgkJCS8vIEZJWE1FOiBuZWVkIHRvIGNoYW5nZSBBUEkgdG8gcGFzcyBpbiByZXF1ZXN0ZXIsIHNvIHRoaXMgZXZlbnQKCQkJLy8gY2FuIGJlCgkJCS8vIGNyZWF0ZWQgY29ycmVjdGx5LCBpbnN0ZWFkIG9mIHVzaW5nIG51bGwuCgkJCU5vQ2hhbmdlRXZlbnQgbm9DaGFuZ2VFdmVudCA9IG5ldyBOb0NoYW5nZUV2ZW50KHRoaXMsIG51bGwsIGFmZmVjdGVkVGV4dCwgc3RhcnRPZmZzZXQsIGxlbmd0aCk7CgkJCW5vQ2hhbmdlRXZlbnQucmVhc29uID0gTm9DaGFuZ2VFdmVudC5SRUFEX09OTFlfU1RBVEVfQ0hBTkdFOwoJCQlmaXJlUmVhZE9ubHlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChub0NoYW5nZUV2ZW50KTsKCQl9CgkJY2F0Y2ggKEJhZExvY2F0aW9uRXhjZXB0aW9uIGUpIHsKCQkJLy8gZm9yIG5vdywgbG9nIGFuZCBpZ25vcmUuIFBlcmhhcHMgbGF0ZXIgd2UKCQkJLy8gY291bGQgYWRqdXN0IHRvIGhhbmRsZSBzb21lIGNhc2VzPwoJCQlMb2dnZXIubG9nRXhjZXB0aW9uKCgiY291bGQgbm90IGNyZWF0ZSByZWFkb25seSByZWdpb24gYXQgIiArIHN0YXJ0T2Zmc2V0ICsgIiB0byAiICsgbGVuZ3RoKSwgZSk7IC8vJE5PTi1OTFMtMSQgLy8kTk9OLU5MUy0yJAoJCX0KCQljYXRjaCAoQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiBlKSB7CgkJCS8vIHNob3VsZCBuZXZlciBvY2N1ciwgc2luY2Ugd2UgYWRkIGNhdGVnb3J5CgkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZSk7CgkJfQoJfQoKCXB1YmxpYyBJU3RydWN0dXJlZERvY3VtZW50IG5ld0luc3RhbmNlKCkgewoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnQgbmV3SW5zdGFuY2UgPSBTdHJ1Y3R1cmVkRG9jdW1lbnRGYWN0b3J5LmdldE5ld1N0cnVjdHVyZWREb2N1bWVudEluc3RhbmNlKGdldFBhcnNlcigpLm5ld0luc3RhbmNlKCkpOwoJCSgoQmFzaWNTdHJ1Y3R1cmVkRG9jdW1lbnQpIG5ld0luc3RhbmNlKS5zZXRSZVBhcnNlcihnZXRSZVBhcnNlcigpLm5ld0luc3RhbmNlKCkpOwoJCWlmIChnZXREb2N1bWVudFBhcnRpdGlvbmVyKCkgaW5zdGFuY2VvZiBTdHJ1Y3R1cmVkVGV4dFBhcnRpdGlvbmVyKSB7CgkJCW5ld0luc3RhbmNlLnNldERvY3VtZW50UGFydGl0aW9uZXIoKChTdHJ1Y3R1cmVkVGV4dFBhcnRpdGlvbmVyKSBnZXREb2N1bWVudFBhcnRpdGlvbmVyKCkpLm5ld0luc3RhbmNlKCkpOwoJCQluZXdJbnN0YW5jZS5nZXREb2N1bWVudFBhcnRpdGlvbmVyKCkuY29ubmVjdChuZXdJbnN0YW5jZSk7CgkJfQoJCW5ld0luc3RhbmNlLnNldExpbmVEZWxpbWl0ZXIoZ2V0TGluZURlbGltaXRlcigpKTsKCQlpZiAoZ2V0RW5jb2RpbmdNZW1lbnRvKCkgIT0gbnVsbCkgewoJCQluZXdJbnN0YW5jZS5zZXRFbmNvZGluZ01lbWVudG8oKEVuY29kaW5nTWVtZW50bykgZ2V0RW5jb2RpbmdNZW1lbnRvKCkuY2xvbmUoKSk7CgkJfQoJCXJldHVybiBuZXdJbnN0YW5jZTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC50ZXh0LklSZWdpb25Db21wYXJpYmxlI3JlZ2lvbk1hdGNoZXMoaW50LAoJICogICAgICBpbnQsIGphdmEubGFuZy5TdHJpbmcpCgkgKi8KCXB1YmxpYyBib29sZWFuIHJlZ2lvbk1hdGNoZXMoaW50IG9mZnNldCwgaW50IGxlbmd0aCwgU3RyaW5nIHN0cmluZ1RvQ29tcGFyZSkgewoJCWJvb2xlYW4gcmVzdWx0ID0gZmFsc2U7CgkJSVRleHRTdG9yZSBzdG9yZSA9IGdldFN0b3JlKCk7CgkJaWYgKHN0b3JlIGluc3RhbmNlb2YgSVJlZ2lvbkNvbXBhcmlibGUpIHsKCQkJcmVzdWx0ID0gKChJUmVnaW9uQ29tcGFyaWJsZSkgc3RvcmUpLnJlZ2lvbk1hdGNoZXMob2Zmc2V0LCBsZW5ndGgsIHN0cmluZ1RvQ29tcGFyZSk7CgkJfQoJCWVsc2UgewoJCQlyZXN1bHQgPSBnZXQob2Zmc2V0LCBsZW5ndGgpLmVxdWFscyhzdHJpbmdUb0NvbXBhcmUpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXB1YmxpYyBib29sZWFuIHJlZ2lvbk1hdGNoZXNJZ25vcmVDYXNlKGludCBvZmZzZXQsIGludCBsZW5ndGgsIFN0cmluZyBzdHJpbmdUb0NvbXBhcmUpIHsKCQlib29sZWFuIHJlc3VsdCA9IGZhbHNlOwoJCUlUZXh0U3RvcmUgc3RvcmUgPSBnZXRTdG9yZSgpOwoJCWlmIChzdG9yZSBpbnN0YW5jZW9mIElSZWdpb25Db21wYXJpYmxlKSB7CgkJCXJlc3VsdCA9ICgoSVJlZ2lvbkNvbXBhcmlibGUpIHN0b3JlKS5yZWdpb25NYXRjaGVzSWdub3JlQ2FzZShvZmZzZXQsIGxlbmd0aCwgc3RyaW5nVG9Db21wYXJlKTsKCQl9CgkJZWxzZSB7CgkJCXJlc3VsdCA9IGdldChvZmZzZXQsIGxlbmd0aCkuZXF1YWxzSWdub3JlQ2FzZShzdHJpbmdUb0NvbXBhcmUpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb24jcmVnaXN0ZXJQb3N0Tm90aWZpY2F0aW9uUmVwbGFjZShvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudExpc3RlbmVyLAoJICogICAgICBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSkKCSAqLwoJcHVibGljIHZvaWQgcmVnaXN0ZXJQb3N0Tm90aWZpY2F0aW9uUmVwbGFjZShJRG9jdW1lbnRMaXN0ZW5lciBvd25lciwgSURvY3VtZW50RXh0ZW5zaW9uLklSZXBsYWNlIHJlcGxhY2UpIHsKCQlpZiAoZkFjY2VwdFBvc3ROb3RpZmljYXRpb25SZXBsYWNlcykgewoJCQlpZiAoZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzID09IG51bGwpCgkJCQlmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMgPSBuZXcgQXJyYXlMaXN0KDEpOwoJCQlmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMuYWRkKG5ldyBSZWdpc3RlcmVkUmVwbGFjZShvd25lciwgcmVwbGFjZSkpOwoJCX0KCX0KCglwcm90ZWN0ZWQgdm9pZCByZWxlYXNlTG9jaygpIHsKCQkvLyBkbyBub3RoaW5nIGhlcmUgaW4gc3VwZXIgY2xhc3MKCX0KCglwdWJsaWMgdm9pZCByZW1vdmVEb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcihJTW9kZWxBYm91dFRvQmVDaGFuZ2VkTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKChmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyAhPSBudWxsKSAmJiAobGlzdGVuZXIgIT0gbnVsbCkpIHsKCQkJCS8vIGlmIGl0cyBub3QgaW4gdGhlIGxpc3RlbmVycywgd2UnbGwgaWdub3JlIHRoZSByZXF1ZXN0CgkJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCQlpbnQgb2xkU2l6ZSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzLmxlbmd0aDsKCQkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgLSAxOwoJCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQkJaW50IGluZGV4ID0gMDsKCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFNpemU7IGkrKykgewoJCQkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnNbaV0gPT0gbGlzdGVuZXIpIHsgLy8gaWdub3JlCgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQkvLyBjb3B5IG9sZCB0byBuZXcgaWYgaXRzIG5vdCB0aGUgb25lIHdlIGFyZQoJCQkJCQkJLy8gcmVtb3ZpbmcKCQkJCQkJCW5ld0xpc3RlbmVyc1tpbmRleCsrXSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzW2ldOwoJCQkJCQl9CgkJCQkJfQoJCQkJCS8vIG5vdyB0aGF0IHdlIGhhdmUgYSBuZXcgYXJyYXksIGxldCdzIHN3aXRjaCBpdCBmb3IgdGhlCgkJCQkJLy8gb2xkCgkJCQkJLy8gb25lCgkJCQkJZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiByZW1vdmVNb2RlbENoYW5nZWRMaXN0ZW5lciBtZXRob2QgY29tbWVudC4KCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXIoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmICgoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMgIT0gbnVsbCkgJiYgKGxpc3RlbmVyICE9IG51bGwpKSB7CgkJCQkvLyBpZiBpdHMgbm90IGluIHRoZSBsaXN0ZW5lcnMsIHdlJ2xsIGlnbm9yZSB0aGUgcmVxdWVzdAoJCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQkJaW50IG9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycy5sZW5ndGg7CgkJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplIC0gMTsKCQkJCQlPYmplY3RbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgT2JqZWN0W25ld1NpemVdOwoJCQkJCWludCBpbmRleCA9IDA7CgkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBvbGRTaXplOyBpKyspIHsKCQkJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzW2ldID09IGxpc3RlbmVyKSB7IC8vIGlnbm9yZQoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJLy8gY29weSBvbGQgdG8gbmV3IGlmIGl0cyBub3QgdGhlIG9uZSB3ZSBhcmUKCQkJCQkJCS8vIHJlbW92aW5nCgkJCQkJCQluZXdMaXN0ZW5lcnNbaW5kZXgrK10gPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVyc1tpXTsKCQkJCQkJfQoJCQkJCX0KCQkJCQkvLyBub3cgdGhhdCB3ZSBoYXZlIGEgbmV3IGFycmF5LCBsZXQncyBzd2l0Y2ggaXQgZm9yIHRoZQoJCQkJCS8vIG9sZAoJCQkJCS8vIG9uZQoJCQkJCWZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJfQoJCQl9CgkJfQoJfQoKCXB1YmxpYyB2b2lkIHJlbW92ZURvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcihJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMgIT0gbnVsbCkgJiYgKGxpc3RlbmVyICE9IG51bGwpKSB7CgkJCQkvLyBpZiBpdHMgbm90IGluIHRoZSBsaXN0ZW5lcnMsIHdlJ2xsIGlnbm9yZSB0aGUgcmVxdWVzdAoJCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJCWludCBvbGRTaXplID0gZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLmxlbmd0aDsKCQkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgLSAxOwoJCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQkJaW50IGluZGV4ID0gMDsKCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFNpemU7IGkrKykgewoJCQkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzW2ldID09IGxpc3RlbmVyKSB7IC8vIGlnbm9yZQoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJLy8gY29weSBvbGQgdG8gbmV3IGlmIGl0cyBub3QgdGhlIG9uZSB3ZSBhcmUKCQkJCQkJCS8vIHJlbW92aW5nCgkJCQkJCQluZXdMaXN0ZW5lcnNbaW5kZXgrK10gPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnNbaV07CgkJCQkJCX0KCQkJCQl9CgkJCQkJLy8gbm93IHRoYXQgd2UgaGF2ZSBhIG5ldyBhcnJheSwgbGV0J3Mgc3dpdGNoIGl0IGZvciB0aGUKCQkJCQkvLyBvbGQKCQkJCQkvLyBvbmUKCQkJCQlmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRMaXN0ZW5lcihJRG9jdW1lbnRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoKGZEb2N1bWVudExpc3RlbmVycyAhPSBudWxsKSAmJiAobGlzdGVuZXIgIT0gbnVsbCkpIHsKCQkJCS8vIGlmIGl0cyBub3QgaW4gdGhlIGxpc3RlbmVycywgd2UnbGwgaWdub3JlIHRoZSByZXF1ZXN0CgkJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZEb2N1bWVudExpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQkJaW50IG9sZFNpemUgPSBmRG9jdW1lbnRMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSAtIDE7CgkJCQkJSURvY3VtZW50TGlzdGVuZXJbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgSURvY3VtZW50TGlzdGVuZXJbbmV3U2l6ZV07CgkJCQkJaW50IGluZGV4ID0gMDsKCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFNpemU7IGkrKykgewoJCQkJCQlpZiAoZkRvY3VtZW50TGlzdGVuZXJzW2ldID09IGxpc3RlbmVyKSB7IC8vIGlnbm9yZQoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJLy8gY29weSBvbGQgdG8gbmV3IGlmIGl0cyBub3QgdGhlIG9uZSB3ZSBhcmUKCQkJCQkJCS8vIHJlbW92aW5nCgkJCQkJCQluZXdMaXN0ZW5lcnNbaW5kZXgrK10gPSBmRG9jdW1lbnRMaXN0ZW5lcnNbaV07CgkJCQkJCX0KCQkJCQl9CgkJCQkJLy8gbm93IHRoYXQgd2UgaGF2ZSBhIG5ldyBhcnJheSwgbGV0J3Mgc3dpdGNoIGl0IGZvciB0aGUKCQkJCQkvLyBvbGQKCQkJCQkvLyBvbmUKCQkJCQlmRG9jdW1lbnRMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJLyoKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnQjcmVtb3ZlRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcihvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCByZW1vdmVEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCUFzc2VydC5pc05vdE51bGwobGlzdGVuZXIpOwoJCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzICE9IG51bGwpCgkJCQlmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMucmVtb3ZlKGxpc3RlbmVyKTsKCQl9Cgl9CgoJLyoqCgkgKiBSZW1vdmVzIHRoZSBnaXZlbiA8Y29kZT5Qb3NpdGlvbjwvY29kZT4gZnJvbSB0aGUgZG9jdW1lbnQncyBkZWZhdWx0CgkgKiBwb3NpdGlvbiBjYXRlZ29yeS4gVGhlIGRlZmF1bHQgcG9zaXRpb24gY2F0ZWdvcnkgaXMgdG8gYmUgZGVmaW5lZCBieQoJICogdGhlIGltcGxlbWVudGVycy4gSWYgdGhlIHBvc2l0aW9uIGlzIG5vdCBwYXJ0IG9mIHRoZSBkb2N1bWVudCdzIGRlZmF1bHQKCSAqIGNhdGVnb3J5IG5vdGhpbmcgaGFwcGVucy4KCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlUG9zaXRpb24oUG9zaXRpb24gcG9zaXRpb24pIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5yZW1vdmVQb3NpdGlvbihwb3NpdGlvbik7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNyZW1vdmVQb3NpdGlvbgoJICogQGV4Y2VwdGlvbiBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiB0aGUgY2F0ZWdvcnkgaXMgbm90IGRlZmluZWQgZm9yIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQb3NpdGlvbihTdHJpbmcgY2F0ZWdvcnksIFBvc2l0aW9uIHBvc2l0aW9uKSB0aHJvd3MgQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkucmVtb3ZlUG9zaXRpb24oY2F0ZWdvcnksIHBvc2l0aW9uKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3JlbW92ZVBvc2l0aW9uQ2F0ZWdvcnkKCSAqIEBleGNlcHRpb24gQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgdGhlIGNhdGVnb3J5IGlzIG5vdCBkZWZpbmVkIGZvciB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlUG9zaXRpb25DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnkpIHRocm93cyBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5yZW1vdmVQb3NpdGlvbkNhdGVnb3J5KGNhdGVnb3J5KTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3JlbW92ZVBvc2l0aW9uVXBkYXRlcgoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQb3NpdGlvblVwZGF0ZXIoSVBvc2l0aW9uVXBkYXRlciB1cGRhdGVyKSB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkucmVtb3ZlUG9zaXRpb25VcGRhdGVyKHVwZGF0ZXIpOwoJfQoKCS8qKgoJICogUmVtb3ZlcyB0aGUgZ2l2ZW4gZG9jdW1lbnQgbGlzdGVuZXIgZnJvbSB0ZWggZG9jdW1lbnQncyBsaXN0IG9mCgkgKiBwcmVub3RpZmllZCBkb2N1bWVudCBsaXN0ZW5lcnMuIElmIHRoZSBsaXN0ZW5lciBpcyBub3QgcmVnaXN0ZXJlZCB3aXRoCgkgKiB0aGUgZG9jdW1lbnQgbm90aGluZyBoYXBwZW5zLgoJICogPHA+CgkgKiAKCSAqIFRoaXMgbWV0aG9kIGlzIG5vdCBmb3IgcHVibGljIHVzZSwgaXQgbWF5IG9ubHkgYmUgY2FsbGVkIGJ5CgkgKiBpbXBsZW1lbnRlcnMgb2YgPGNvZGU+SURvY3VtZW50QWRhcHRlcjwvY29kZT4gYW5kIG9ubHkgaWYgdGhvc2UKCSAqIGltcGxlbWVudGVycyBuZWVkIHRvIGltcGxlbWVudCA8Y29kZT5JRG9jdW1lbnRMaXN0ZW5lcjwvY29kZT4uCgkgKiAKCSAqIEBwYXJhbSBkb2N1bWVudEFkYXB0ZXIKCSAqICAgICAgICAgICAgdGhlIGxpc3RlbmVyIHRvIGJlIHJlbW92ZWQKCSAqIAoJICogQHNlZSAjYWRkUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVyKElEb2N1bWVudExpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXIob3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRMaXN0ZW5lciBkb2N1bWVudEFkYXB0ZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgZG9jdW1lbnRBZGFwdGVyKSkgewoJCQkJaW50IHByZXZpb3VzU2l6ZSA9IGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLmxlbmd0aDsKCQkJCWlmIChwcmV2aW91c1NpemUgPiAxKSB7CgkJCQkJSURvY3VtZW50TGlzdGVuZXJbXSBsaXN0ZW5lcnMgPSBuZXcgSURvY3VtZW50TGlzdGVuZXJbcHJldmlvdXNTaXplIC0gMV07CgkJCQkJaW50IHByZXZpb3VzSW5kZXggPSAwOwoJCQkJCWludCBuZXdJbmRleCA9IDA7CgkJCQkJd2hpbGUgKHByZXZpb3VzSW5kZXggPCBwcmV2aW91c1NpemUpIHsKCQkJCQkJaWYgKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzW3ByZXZpb3VzSW5kZXhdICE9IGRvY3VtZW50QWRhcHRlcikKCQkJCQkJCWxpc3RlbmVyc1tuZXdJbmRleCsrXSA9IGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzW3ByZXZpb3VzSW5kZXhdOwoJCQkJCQlwcmV2aW91c0luZGV4Kys7CgkJCQkJfQoJCQkJCWZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMgPSBudWxsOwoJCQkJfQoJCQl9CgkJfQoJfQoKCS8qKgoJICogVGhpcyBtZXRob2QgaXMgZm9yIElOVEVSTkFMIFVTRSBPTkxZIGFuZCBpcyBOT1QgQVBJLgoJICogCgkgKiBSZWJ1aWxkcyB0aGUgU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGNoYWluIGZyb20gdGhlIGV4aXN0aW5nIHRleHQuCgkgKiBGaWxlQnVmZmVyIHN1cHBvcnQgZG9lcyBub3QgYWxsb3cgY2xpZW50cyB0byBrbm93IHRoZSBkb2N1bWVudCdzCgkgKiBsb2NhdGlvbiBiZWZvcmUgdGhlIHRleHQgY29udGVudHMgYXJlIHNldC4KCSAqIAoJICogQHNlZSBzZXQoU3RyaW5nKQoJICovCglwdWJsaWMgdm9pZCByZXBhcnNlKE9iamVjdCByZXF1ZXN0ZXIpIHsKCQlzdG9wUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCQljbGVhclJlYWRPbmx5KCk7CgoJCXRyeSB7CgkJCWFjcXVpcmVMb2NrKCk7CgkJCQoJCQlDaGFyU2VxdWVuY2VSZWFkZXIgc3ViU2V0VGV4dFN0b3JlUmVhZGVyID0gbmV3IENoYXJTZXF1ZW5jZVJlYWRlcigoQ2hhclNlcXVlbmNlKSBnZXRTdG9yZSgpLCAwLCBnZXRTdG9yZSgpLmdldExlbmd0aCgpKTsKCQkJcmVzZXRQYXJzZXIoc3ViU2V0VGV4dFN0b3JlUmVhZGVyLCAwKTsKCQkJLy8KCQkJc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oZ2V0UGFyc2VyKCkuZ2V0RG9jdW1lbnRSZWdpb25zKCkpOwoJCQkvLyB3aGVuIHN0YXJ0aW5nIGFmcmVzaCwgb3VyIGNhY2hlZE5vZGUgc2hvdWxkIGJlIG91ciBmaXJzdE5vZGUsCgkJCS8vIHNvIGJlIHN1cmUgdG8gaW5pdGlhbGl6ZSB0aGUgZmlyc3ROb2RlIGFuZCBsYXN0Tm9kZQoJCQlpbml0aWFsaXplRmlyc3RBbmRMYXN0RG9jdW1lbnRSZWdpb24oKTsKCQkJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uSXRlcmF0b3Iuc2V0UGFyZW50RG9jdW1lbnQoZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKSwgdGhpcyk7CgkJfQoJCWZpbmFsbHkgewoJCQlyZWxlYXNlTG9jaygpOwoJCX0KCgkJcmVzdW1lUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3JlcGxhY2UKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHBvc2l0aW9uIGlzIG5vdCBhIHZhbGlkIHJhbmdlIGluIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgdm9pZCByZXBsYWNlKGludCBvZmZzZXQsIGludCBsZW5ndGgsIFN0cmluZyB0ZXh0KSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCWlmIChEZWJ1Zy5kaXNwbGF5V2FybmluZ3MpIHsKCQkJU3lzdGVtLm91dC5wcmludGxuKCJOb3RlOiBJU3RydWN0dXJlZERvY3VtZW50OjpyZXBsYWNlKGludCwgaW50LCBTdHJpbmcpIC4uLi4gaXRzIGJldHRlciB0byB1c2UgcmVwbGFjZVRleHQoc291cmNlLCBzdHJpbmcsIGludCwgaW50KSBBUEkgZm9yIHN0cnVjdHVyZWREb2N1bWVudCB1cGRhdGVzIik7IC8vJE5PTi1OTFMtMSQKCQl9CgkJcmVwbGFjZVRleHQodGhpcywgb2Zmc2V0LCBsZW5ndGgsIHRleHQpOwoJfQoKCS8qKgoJICogUmVwbGFjZSB0aGUgdGV4dCB3aXRoICJuZXdUZXh0IiBzdGFydGluZyBhdCBwb3NpdGlvbiAic3RhcnQiIGZvciBhCgkgKiBsZW5ndGggb2YgInJlcGxhY2VMZW5ndGgiLgoJICogPHA+CgkgKiAKCSAqIEBwYXJhbSBwb3MKCSAqICAgICAgICAgICAgc3RhcnQgb2Zmc2V0IG9mIHRleHQgdG8gcmVwbGFjZSBOb25lIG9mIHRoZSBvZmZzZXRzIGluY2x1ZGUKCSAqICAgICAgICAgICAgZGVsaW1pdGVycyBvZiBwcmVjZWVkaW5nIGxpbmVzLiBPZmZzZXQgMCBpcyB0aGUgZmlyc3QKCSAqICAgICAgICAgICAgY2hhcmFjdGVyIG9mIHRoZSBkb2N1bWVudC4KCSAqIEBwYXJhbSBsZW5ndGgKCSAqICAgICAgICAgICAgc3RhcnQgb2Zmc2V0IG9mIHRleHQgdG8gcmVwbGFjZQoJICogQHBhcmFtIHRleHQKCSAqICAgICAgICAgICAgc3RhcnQgb2Zmc2V0IG9mIHRleHQgdG8gcmVwbGFjZQoJICogICAgICAgICAgICA8cD4KCSAqICAgICAgICAgICAgSW1wbGVtZW50b3JzIGhhdmUgdG8gbm90aWZ5IFRleHRDaGFuZ2VkIGxpc3RlbmVycyBhZnRlciB0aGUKCSAqICAgICAgICAgICAgY29udGVudCBoYXMgYmVlbiB1cGRhdGVkLiBUaGUgVGV4dENoYW5nZWRFdmVudCBzaG91bGQgYmUgc2V0CgkgKiAgICAgICAgICAgIGFzIGZvbGxvd3M6CgkgKiAKCSAqIGV2ZW50LnR5cGUgPSBTV1QuVGV4dFJlcGxhY2VkIGV2ZW50LnN0YXJ0ID0gc3RhcnQgb2YgdGhlIHJlcGxhY2VkIHRleHQKCSAqIGV2ZW50Lm51bVJlcGxhY2VkTGluZXMgPSBudW1iZXIgb2YgcmVwbGFjZWQgbGluZXMgZXZlbnQubnVtTmV3TGluZXMgPQoJICogbnVtYmVyIG9mIG5ldyBsaW5lcyBldmVudC5yZXBsYWNlZExlbmd0aCA9IGxlbmd0aCBvZiB0aGUgcmVwbGFjZWQgdGV4dAoJICogZXZlbnQubmV3TGVuZ3RoID0gbGVuZ3RoIG9mIHRoZSBuZXcgdGV4dAoJICogCgkgKiBOT1RFOiBudW1OZXdMaW5lcyBpcyB0aGUgbnVtYmVyIG9mIGluc2VydGVkIGxpbmVzIGFuZCBudW1SZXBsYWNlZExpbmVzCgkgKiBpcyB0aGUgbnVtYmVyIG9mIGRlbGV0ZWQgbGluZXMgYmFzZWQgb24gdGhlIGNoYW5nZSB0aGF0IG9jY3VycwoJICogdmlzdWFsbHkuIEZvciBleGFtcGxlOgoJICogCgkgKiByZXBsYWNlZFRleHQgbmV3VGV4dCBudW1SZXBsYWNlZExpbmVzIG51bU5ld0xpbmVzICIiICJcbiIgMCAxICJcblxuIgoJICogImEiIDIgMCAiYSIgIlxuXG4iIDAgMgoJICovCgkvKioKCSAqIE9uZSBvZiB0aGUgQVBJcyB0byBtYW5pcHVsYXRlIHRoZSBJU3RydWN0dXJlZERvY3VtZW50IGluIHRlcm1zIG9mIHRleHQuCgkgKi8KCXB1YmxpYyBTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCByZXBsYWNlVGV4dChPYmplY3QgcmVxdWVzdGVyLCBpbnQgcG9zLCBpbnQgbGVuZ3RoLCBTdHJpbmcgdGV4dCkgewoJCWlmIChsZW5ndGggPT0gMCAmJiAodGV4dCA9PSBudWxsIHx8IHRleHQubGVuZ3RoKCkgPT0gMCkpCgkJCXJldHVybiByZXBsYWNlVGV4dChyZXF1ZXN0ZXIsIHBvcywgbGVuZ3RoLCB0ZXh0LCBnZXRNb2RpZmljYXRpb25TdGFtcCgpLCB0cnVlKTsKCQllbHNlCgkJCXJldHVybiByZXBsYWNlVGV4dChyZXF1ZXN0ZXIsIHBvcywgbGVuZ3RoLCB0ZXh0LCBnZXROZXh0TW9kaWZpY2F0aW9uU3RhbXAoKSwgdHJ1ZSk7Cgl9CgoJcHVibGljIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHJlcGxhY2VUZXh0KE9iamVjdCByZXF1ZXN0ZXIsIGludCBzdGFydCwgaW50IHJlcGxhY2VtZW50TGVuZ3RoLCBTdHJpbmcgY2hhbmdlcywgYm9vbGVhbiBpZ25vcmVSZWFkT25seVNldHRpbmdzKSB7CgkJbG9uZyBtb2RpZmljYXRpb25TdGFtcDsKCQkKCQlpZiAocmVwbGFjZW1lbnRMZW5ndGggPT0gMCAmJiAoY2hhbmdlcyA9PSBudWxsIHx8IGNoYW5nZXMubGVuZ3RoKCkgPT0gMCkpCgkJCW1vZGlmaWNhdGlvblN0YW1wID0gZ2V0TW9kaWZpY2F0aW9uU3RhbXAoKTsKCQllbHNlCgkJCW1vZGlmaWNhdGlvblN0YW1wID0gZ2V0TmV4dE1vZGlmaWNhdGlvblN0YW1wKCk7CgkJCgkJcmV0dXJuIHJlcGxhY2VUZXh0KHJlcXVlc3Rlciwgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoLCBjaGFuZ2VzLCBtb2RpZmljYXRpb25TdGFtcCwgaWdub3JlUmVhZE9ubHlTZXR0aW5ncyk7Cgl9CgkKCXByaXZhdGUgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgcmVwbGFjZVRleHQoT2JqZWN0IHJlcXVlc3RlciwgaW50IHN0YXJ0LCBpbnQgcmVwbGFjZW1lbnRMZW5ndGgsIFN0cmluZyBjaGFuZ2VzLCBsb25nIG1vZGlmaWNhdGlvblN0YW1wLCBib29sZWFuIGlnbm9yZVJlYWRPbmx5U2V0dGluZ3MpIHsKCQlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCBldmVudCA9IGludGVybmFsUmVwbGFjZVRleHQocmVxdWVzdGVyLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgsIGNoYW5nZXMsIG1vZGlmaWNhdGlvblN0YW1wLCBpZ25vcmVSZWFkT25seVNldHRpbmdzKTsKCQlyZXR1cm4gZXZlbnQ7Cgl9CgoJdm9pZCByZXNldFBhcnNlcihpbnQgc3RhcnRPZmZzZXQsIGludCBlbmRPZmZzZXQpIHsKCgkJUmVnaW9uUGFyc2VyIHBhcnNlciA9IGdldFBhcnNlcigpOwoJCUlUZXh0U3RvcmUgdGV4dFN0b3JlID0gZ2V0U3RvcmUoKTsKCQlpZiAodGV4dFN0b3JlIGluc3RhbmNlb2YgQ2hhclNlcXVlbmNlKSB7CgkJCUNoYXJTZXF1ZW5jZVJlYWRlciBzdWJTZXRUZXh0U3RvcmVSZWFkZXIgPSBuZXcgQ2hhclNlcXVlbmNlUmVhZGVyKChDaGFyU2VxdWVuY2UpIHRleHRTdG9yZSwgc3RhcnRPZmZzZXQsIGVuZE9mZnNldCAtIHN0YXJ0T2Zmc2V0KTsKCQkJcGFyc2VyLnJlc2V0KHN1YlNldFRleHRTdG9yZVJlYWRlciwgc3RhcnRPZmZzZXQpOwoJCX0KCQllbHNlIHsKCQkJU3RyaW5nIG5ld05vZGVUZXh0ID0gZ2V0KHN0YXJ0T2Zmc2V0LCBlbmRPZmZzZXQgLSBzdGFydE9mZnNldCk7CgkJCXBhcnNlci5yZXNldChuZXdOb2RlVGV4dCwgc3RhcnRPZmZzZXQpOwoKCQl9CgoJfQoKCXZvaWQgcmVzZXRQYXJzZXIoUmVhZGVyIHJlYWRlciwgaW50IHN0YXJ0T2Zmc2V0KSB7CgkJUmVnaW9uUGFyc2VyIHBhcnNlciA9IGdldFBhcnNlcigpOwoJCXBhcnNlci5yZXNldChyZWFkZXIsIHN0YXJ0T2Zmc2V0KTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uI3Jlc3VtZVBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCkKCSAqLwoJcHVibGljIHZvaWQgcmVzdW1lUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKSB7CgkJLS1mU3RvcHBlZENvdW50OwoJCWlmIChmU3RvcHBlZENvdW50ID09IDAgJiYgZlJlZW50cmFuY2VDb3VudCA9PSAwKQoJCQlleGVjdXRlUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMoKTsKCX0KCgkvKioKCSAqIEBkZXByZWNhdGVkIGluIHN1cGVyY2xhc3MgaW4gMy4wIC0gdXNlIGEgRmluZFJlcGxhY2VEb2N1bWVudEFkYXB0ZXIKCSAqICAgICAgICAgICAgIGRpcmVjdGx5CgkgKiBAc2VlIElEb2N1bWVudCNzZWFyY2gKCSAqLwoJcHVibGljIGludCBzZWFyY2goaW50IHN0YXJ0UG9zaXRpb24sIFN0cmluZyBmaW5kU3RyaW5nLCBib29sZWFuIGZvcndhcmRTZWFyY2gsIGJvb2xlYW4gY2FzZVNlbnNpdGl2ZSwgYm9vbGVhbiB3aG9sZVdvcmQpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJLy8gKGRtdykgSSBhZGRlZCB0aGlzIHdhcm5pbmcsIHRvIGtub3cgaWYgc3RpbGwgYmVpbmcgdXNlZC4gSSdtIG5vdAoJCS8vIHN1cmUgaXQKCQkvLyB3b3JrcyBhcyBleHBlY3RlZCBhbnkgbG9uZ2VyLgoJCS8vIGJ1dCB0aGUgd2FybmluZyBzaG91bGQgYmUgcmVtb3ZlZCwgb25jZSBrbm93LgoJCUxvZ2dlci5sb2coTG9nZ2VyLklORk8sICJXQVJOSU5HOiB1c2luZyB1bnN1cHBvcnRlZCBkZXByZWNhdGVkIG1ldGhvZCAnc2VhcmNoJyIpOyAvLyROT04tTkxTLTEkCgkJaW50IG9mZnNldCA9IC0xOwoJCUlSZWdpb24gbWF0Y2ggPSBuZXcgRmluZFJlcGxhY2VEb2N1bWVudEFkYXB0ZXIodGhpcykuZmluZChzdGFydFBvc2l0aW9uLCBmaW5kU3RyaW5nLCBmb3J3YXJkU2VhcmNoLCBjYXNlU2Vuc2l0aXZlLCB3aG9sZVdvcmQsIGZhbHNlKTsKCQlpZiAobWF0Y2ggIT0gbnVsbCkgewoJCQlvZmZzZXQgPSBtYXRjaC5nZXRPZmZzZXQoKTsKCQl9CgkJcmV0dXJuIG9mZnNldDsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3NldFRleHQKCSAqLwoJcHVibGljIHZvaWQgc2V0KFN0cmluZyBzdHJpbmcpIHsKCQlpZiAoRGVidWcuZGlzcGxheUluZm8pIHsKCQkJU3lzdGVtLm91dC5wcmludGxuKCJOb3RlOiBJU3RydWN0dXJlZERvY3VtZW50OjpzZXRUZXh0KFN0cmluZykgLi4uLiBpdHMgYmV0dGVyIHRvIHVzZSBzZXRUZXh0KHNvdXJjZSwgc3RyaW5nKSBBUEkgZm9yIHN0cnVjdHVyZWREb2N1bWVudCB1cGRhdGVzIik7IC8vJE5PTi1OTFMtMSQKCQl9CgkJc2V0VGV4dChudWxsLCBzdHJpbmcpOwoJfQoKCS8qKgoJICogVGhpcyBtYXkgYmUgbWFya2VkIHB1YmxpYywgYnV0IHNob3VsZCBiZSBwYWNrYWdlZCBwcm90ZWN0ZWQsIG9uY2UKCSAqIHJlZmFjdG9yaW5nIGlzIGNvbXBsZXRlIChpbiBvdGhlciB3b3Jkcywgbm90IGZvciBjbGllbnQgdXNlKS4KCSAqLwoJcHVibGljIHZvaWQgc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBzdHJ1Y3R1cmVkUmVnaW9uKSB7CgkJaWYgKFVTRV9MT0NBTF9USFJFQUQpIHsKCQkJZkN1cnJlbnREb2N1bW5ldFJlZ2lvbkNhY2hlLnNldChzdHJ1Y3R1cmVkUmVnaW9uKTsKCQl9CgkJZWxzZSB7CgkJCWNhY2hlZERvY3VtZW50UmVnaW9uID0gc3RydWN0dXJlZFJlZ2lvbjsKCQl9Cgl9CgoJLyoqCgkgKiBTZXRzIHRoZSBkb2N1bWVudCdzIHBhcnRpdGlvbmVyLgoJICogCgkgKiBAc2VlIElEb2N1bWVudFBhcnRpdGlvbmVyCgkgKi8KCXB1YmxpYyB2b2lkIHNldERvY3VtZW50UGFydGl0aW9uZXIoSURvY3VtZW50UGFydGl0aW9uZXIgcGFydGl0aW9uZXIpIHsKCQlzZXREb2N1bWVudFBhcnRpdGlvbmVyKElEb2N1bWVudEV4dGVuc2lvbjMuREVGQVVMVF9QQVJUSVRJT05JTkcsIHBhcnRpdGlvbmVyKTsKCX0KCgoJcHVibGljIHZvaWQgc2V0RG9jdW1lbnRQYXJ0aXRpb25lcihTdHJpbmcgcGFydGl0aW9uaW5nLCBJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lcikgewoJCWlmIChwYXJ0aXRpb25lciA9PSBudWxsKSB7CgkJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgIT0gbnVsbCkgewoJCQkJZkRvY3VtZW50UGFydGl0aW9uZXJzLnJlbW92ZShwYXJ0aXRpb25pbmcpOwoJCQkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycy5zaXplKCkgPT0gMCkKCQkJCQlmRG9jdW1lbnRQYXJ0aXRpb25lcnMgPSBudWxsOwoJCQl9CgkJfQoJCWVsc2UgewoJCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzID09IG51bGwpCgkJCQlmRG9jdW1lbnRQYXJ0aXRpb25lcnMgPSBuZXcgSGFzaE1hcCgpOwoJCQlmRG9jdW1lbnRQYXJ0aXRpb25lcnMucHV0KHBhcnRpdGlvbmluZywgcGFydGl0aW9uZXIpOwoJCX0KCQlEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWRFdmVudCBldmVudCA9IG5ldyBEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWRFdmVudCh0aGlzKTsKCQlldmVudC5zZXRQYXJ0aXRpb25DaGFuZ2UocGFydGl0aW9uaW5nLCAwLCBnZXRMZW5ndGgoKSk7CgkJZmlyZURvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZChldmVudCk7Cgl9CgoJcHVibGljIHZvaWQgc2V0RW5jb2RpbmdNZW1lbnRvKEVuY29kaW5nTWVtZW50byBlbmNvZGluZ01lbWVudG8pIHsKCQl0aGlzLmVuY29kaW5nTWVtZW50byA9IGVuY29kaW5nTWVtZW50bzsKCX0KCgl2b2lkIHNldEZpcnN0RG9jdW1lbnRSZWdpb24oSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24pIHsKCQlmaXJzdERvY3VtZW50UmVnaW9uID0gcmVnaW9uOwoKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNzZXRJbml0aWFsTGluZURlbGltaXRlcihqYXZhLmxhbmcuU3RyaW5nKQoJICovCglwdWJsaWMgdm9pZCBzZXRJbml0aWFsTGluZURlbGltaXRlcihTdHJpbmcgbGluZURlbGltaXRlcikgewoJCS8vIG1ha2Ugc3VyZSBvdXIgcHJlZmVycmVkIGRlbGltaXRlciBpcwoJCS8vIG9uZSBvZiB0aGUgbGVnYWwgb25lcwoJCWlmIChVdGlsaXRpZXMuY29udGFpbnNTdHJpbmcoZ2V0TGVnYWxMaW5lRGVsaW1pdGVycygpLCBsaW5lRGVsaW1pdGVyKSkgewoJCQlmSW5pdGlhbExpbmVEZWxpbWl0ZXI9IGxpbmVEZWxpbWl0ZXI7CgkJfQoJCWVsc2UgewoJCQlpZiAoTG9nZ2VyLkRFQlVHX0RPQ1VNRU5UKQoJCQkJTG9nZ2VyLmxvZyhMb2dnZXIuSU5GTywgIkF0dGVtcHQgdG8gc2V0IGxpbmVkZWxpbWl0ZXIgdG8gbm9uLWxlZ2FsIGRlbGltaXRlciIpOyAvLyROT04tTkxTLTEkIC8vJE5PTi1OTFMtMiQKCQkJZkluaXRpYWxMaW5lRGVsaW1pdGVyID0gUGxhdGZvcm0uZ2V0UHJlZmVyZW5jZXNTZXJ2aWNlKCkuZ2V0U3RyaW5nKFBsYXRmb3JtLlBJX1JVTlRJTUUsIFBsYXRmb3JtLlBSRUZfTElORV9TRVBBUkFUT1IsIFN5c3RlbS5nZXRQcm9wZXJ0eSgibGluZS5zZXBhcmF0b3IiKSwgbmV3IElTY29wZUNvbnRleHRbXSB7IG5ldyBJbnN0YW5jZVNjb3BlKCkgfSk7Ly8kTk9OLU5MUy0xJAoJCX0KCX0KCgl2b2lkIHNldExhc3REb2N1bWVudFJlZ2lvbihJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlZ2lvbikgewoJCWxhc3REb2N1bWVudFJlZ2lvbiA9IHJlZ2lvbjsKCgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZERvY3VtZW50I3NldExpbmVEZWxpbWl0ZXIoamF2YS5sYW5nLlN0cmluZykKCSAqLwoJcHVibGljIHZvaWQgc2V0TGluZURlbGltaXRlcihTdHJpbmcgZGVsaW1pdGVyKSB7CgkJc2V0SW5pdGlhbExpbmVEZWxpbWl0ZXIoZGVsaW1pdGVyKTsKCX0KCgkvKioKCSAqIFNldHMgdGhlIGRvY3VtZW50J3MgbGluZSB0cmFja2VyLiBNdXN0IGJlIGNhbGxlZCBhdCB0aGUgYmVnaW5uaW5nIG9mCgkgKiB0aGUgY29uc3RydWN0b3IuCgkgKiAKCSAqIEBwYXJhbSB0cmFja2VyCgkgKiAgICAgICAgICAgIHRoZSBkb2N1bWVudCdzIGxpbmUgdHJhY2tlcgoJICovCglwcml2YXRlIHZvaWQgc2V0TGluZVRyYWNrZXIoSUxpbmVUcmFja2VyIHRyYWNrZXIpIHsKCQlmVHJhY2tlciA9IHRyYWNrZXI7Cgl9CgoJcHVibGljIHZvaWQgc2V0UGFyc2VyKFJlZ2lvblBhcnNlciBuZXdQYXJzZXIpIHsKCQlpbnRlcm5hbF9zZXRQYXJzZXIobmV3UGFyc2VyKTsKCX0KCgkvKioKCSAqIEBwYXJhbSBwb3NpdGlvbk1hbmFnZXIKCSAqICAgICAgICAgICAgVGhlIHBvc2l0aW9uTWFuYWdlciB0byBzZXQuCgkgKi8KCS8vIFRPRE86IG1ha2UgcHJpdmF0ZSBpcyBuZWVkZWQsIGVsc2UgcmVtb3ZlCgl2b2lkIHNldFBvc2l0aW9uTWFuYWdlcihHZW5lcmljUG9zaXRpb25NYW5hZ2VyIHBvc2l0aW9uTWFuYWdlcikgewoJCWZQb3NpdGlvbk1hbmFnZXIgPSBwb3NpdGlvbk1hbmFnZXI7Cgl9CgoJLyoqCgkgKiAKCSAqLwoJcHVibGljIHZvaWQgc2V0UmVQYXJzZXIoSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgbmV3UmVQYXJzZXIpIHsKCQlmUmVQYXJzZXIgPSBuZXdSZVBhcnNlcjsKCQlpZiAoZlJlUGFyc2VyICE9IG51bGwpIHsKCQkJZlJlUGFyc2VyLnNldFN0cnVjdHVyZWREb2N1bWVudCh0aGlzKTsKCQl9Cgl9CgoJLyoqCgkgKiBPbmUgb2YgdGhlIEFQSXMgdG8gbWFuaXB1bGF0ZSB0aGUgSVN0cnVjdHVyZWREb2N1bWVudCBpbiB0ZXJtcyBvZiB0ZXh0LgoJICovCglwdWJsaWMgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgc2V0VGV4dChPYmplY3QgcmVxdWVzdGVyLCBTdHJpbmcgdGhlU3RyaW5nKSB7CgkJU3RydWN0dXJlZERvY3VtZW50RXZlbnQgcmVzdWx0ID0gbnVsbDsKCQlyZXN1bHQgPSByZXBsYWNlVGV4dChyZXF1ZXN0ZXIsIDAsIGdldExlbmd0aCgpLCB0aGVTdHJpbmcsIGdldE5leHRNb2RpZmljYXRpb25TdGFtcCgpLCB0cnVlKTsKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qKgoJICogU2V0cyB0aGUgZG9jdW1lbnQncyB0ZXh0IHN0b3JlLiBNdXN0IGJlIGNhbGxlZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZQoJICogY29uc3RydWN0b3IuCgkgKiAKCSAqIEBwYXJhbSBzdG9yZQoJICogICAgICAgICAgICB0aGUgZG9jdW1lbnQncyB0ZXh0IHN0b3JlCgkgKi8KCXByaXZhdGUgdm9pZCBzZXRUZXh0U3RvcmUoSVRleHRTdG9yZSBzdG9yZSkgewoJCUFzc2VydC5pc05vdE51bGwoc3RvcmUpOwoJCWZTdG9yZSA9IHN0b3JlOwoJfQoKCXB1YmxpYyB2b2lkIHNldFVuZG9NYW5hZ2VyKElTdHJ1Y3R1cmVkVGV4dFVuZG9NYW5hZ2VyIHVuZG9NYW5hZ2VyKSB7CgoJCS8vIGlmIHRoZSB1bmRvIG1hbmFnZXIgaGFzIGFscmVhZHkgYmVlbiBzZXQsIHRoZW4KCQkvLyBmYWlsIGZhc3QsIHNpbmNlIGNoYW5naW5nIHRoZSB1bmRvIG1hbmFnZXIgd2lsbCBsZWFkCgkJLy8gdG8gdW51c3VhbCByZXN1bHRzIChvciBhdCBsZWFzdCBsb3NzIG9mIHVuZG8gc3RhY2spLgoJCWlmIChmVW5kb01hbmFnZXIgIT0gbnVsbCAmJiBmVW5kb01hbmFnZXIgIT0gdW5kb01hbmFnZXIpIHsKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiY2FuIG5vdCBjaGFuZ2UgdW5kbyBtYW5hZ2VyIG9uY2UgaXRzIGJlZW4gc2V0Iik7IC8vJE5PTi1OTFMtMSQKCQl9CgkJZWxzZSB7CgkJCWZVbmRvTWFuYWdlciA9IHVuZG9NYW5hZ2VyOwoJCX0KCX0KCgoJcHVibGljIHZvaWQgc3RhcnRTZXF1ZW50aWFsUmV3cml0ZShib29sZWFuIG5vcm1hbGl6ZWQpIHsKCQlJVGV4dFN0b3JlIHN0b3JlID0gbmV3IFNlcXVlbnRpYWxSZXdyaXRlVGV4dFN0b3JlKGdldFN0b3JlKCkpOwoJCXNldFRleHRTdG9yZShzdG9yZSk7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbiNzdG9wUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKQoJICovCglwdWJsaWMgdm9pZCBzdG9wUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKSB7CgkJKytmU3RvcHBlZENvdW50OwoJfQoKCglwdWJsaWMgdm9pZCBzdG9wU2VxdWVudGlhbFJld3JpdGUoKSB7CgkJaWYgKGdldFN0b3JlKCkgaW5zdGFuY2VvZiBTZXF1ZW50aWFsUmV3cml0ZVRleHRTdG9yZSkgewoJCQlTZXF1ZW50aWFsUmV3cml0ZVRleHRTdG9yZSBzcndzID0gKFNlcXVlbnRpYWxSZXdyaXRlVGV4dFN0b3JlKSBnZXRTdG9yZSgpOwoJCQlJVGV4dFN0b3JlIHNvdXJjZSA9IHNyd3MuZ2V0U291cmNlU3RvcmUoKTsKCQkJc2V0VGV4dFN0b3JlKHNvdXJjZSk7CgkJCXNyd3MuZGlzcG9zZSgpOwoJCX0KCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIGphdmEubGFuZy5DaGFyU2VxdWVuY2Ujc3ViU2VxdWVuY2UoaW50LCBpbnQpCgkgKi8KCXB1YmxpYyBDaGFyU2VxdWVuY2Ugc3ViU2VxdWVuY2UoaW50IGFyZzAsIGludCBhcmcxKSB7CgkJcmV0dXJuIGdldChhcmcwLCBhcmcxKTsKCX0KCgkvKioKCSAqIEBwYXJhbSByZXN1bHQKCSAqLwoJcHJpdmF0ZSB2b2lkIHVwZGF0ZURlbGV0ZWRGaWVsZHMoU3RydWN0dXJlZERvY3VtZW50UmVnaW9uc1JlcGxhY2VkRXZlbnQgZXZlbnQpIHsKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uTGlzdCBvbGRSZWdpb25zID0gZXZlbnQuZ2V0T2xkU3RydWN0dXJlZERvY3VtZW50UmVnaW9ucygpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgb2xkUmVnaW9ucy5nZXRMZW5ndGgoKTsgaSsrKSB7CgkJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gc3RydWN0dXJlZERvY3VtZW50UmVnaW9uID0gb2xkUmVnaW9ucy5pdGVtKGkpOwoJCQlzdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24uc2V0RGVsZXRlZCh0cnVlKTsKCQl9CgoJfQoKCS8qKgoJICogQ2FsbGVkIGJ5IHJlLXBhcnNlci4gTm90ZTogdGhpcyBtZXRob2QgbWF5IGJlICJwdWJsaWMiIGJ1dCBzaG91bGQgb25seQoJICogYmUgY2FsbGVkIGJ5IHJlLXBhcnNlcnMgaW4gdGhlIHJpZ2h0IGNpcmN1bXN0YW5jZXMuCgkgKi8KCXB1YmxpYyB2b2lkIHVwZGF0ZURvY3VtZW50RGF0YShpbnQgc3RhcnQsIGludCBsZW5ndGhUb1JlcGxhY2UsIFN0cmluZyBjaGFuZ2VzKSB7CgkJc3RvcFBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCk7CgkJZ2V0U3RvcmUoKS5yZXBsYWNlKHN0YXJ0LCBsZW5ndGhUb1JlcGxhY2UsIGNoYW5nZXMpOwoJCXRyeSB7CgkJCWdldFRyYWNrZXIoKS5yZXBsYWNlKHN0YXJ0LCBsZW5ndGhUb1JlcGxhY2UsIGNoYW5nZXMpOwoJCX0KCgkJY2F0Y2ggKEJhZExvY2F0aW9uRXhjZXB0aW9uIGUpIHsKCQkJLy8gc2hvdWxkIGJlIGltcG9zc2libGUgaGVyZSwgYnV0IHdpbGwgbG9nIGZvciBub3cKCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihlKTsKCQl9CgkJaWYgKGZQb3NpdGlvbk1hbmFnZXIgIT0gbnVsbCkgewoJCQlmUG9zaXRpb25NYW5hZ2VyLnVwZGF0ZVBvc2l0aW9ucyhuZXcgRG9jdW1lbnRFdmVudCh0aGlzLCBzdGFydCwgbGVuZ3RoVG9SZXBsYWNlLCBjaGFuZ2VzKSk7CgkJfQoJCWZNb2RpZmljYXRpb25TdGFtcCsrOwoJCWZOZXh0TW9kaWZpY2F0aW9uU3RhbXA9IE1hdGgubWF4KGZNb2RpZmljYXRpb25TdGFtcCwgZk5leHRNb2RpZmljYXRpb25TdGFtcCk7CgkJcmVzdW1lUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCX0KCglwcml2YXRlIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHVwZGF0ZU1vZGVsKE9iamVjdCByZXF1ZXN0ZXIsIGludCBzdGFydCwgaW50IGxlbmd0aFRvUmVwbGFjZSwgU3RyaW5nIGNoYW5nZXMpIHsKCQlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCByZXN1bHQgPSBudWxsOwoJCUlTdHJ1Y3R1cmVkVGV4dFJlUGFyc2VyIHJlUGFyc2VyID0gZ2V0UmVQYXJzZXIoKTsKCQkvLyBpbml0aWFsaXplIHRoZSBJU3RydWN0dXJlZFRleHRSZVBhcnNlciB3aXRoIHRoZSBzdGFuZGFyZCBkYXRhCgkJLy8gdGhhdCdzCgkJLy8gYWx3YXlzIG5lZWRlZAoJCXJlUGFyc2VyLmluaXRpYWxpemUocmVxdWVzdGVyLCBzdGFydCwgbGVuZ3RoVG9SZXBsYWNlLCBjaGFuZ2VzKTsKCQlyZXN1bHQgPSByZVBhcnNlci5yZXBhcnNlKCk7CgkJLy8gaWYgcmVzdWx0IGlzIG51bGwgYXQgdGhpcyBwb2ludCwgdGhlbiB0aGVyZSBtdXN0IGJlIGFuIGVycm9yLCBzaW5jZQoJCS8vIGV2ZW4gaWYgdGhlcmUKCQkvLyB3YXMgbm8gY2hhbmdlIChlaXRoZXIgZGlzYWxsb3cgZHVlIHRvIHJlYWRvbmx5LCBvciBhIHBlcnNvbiBwYXN0ZWQKCQkvLyB0aGUgc2FtZSB0aGluZwoJCS8vIHRoZXkgaGFkIHNlbGVjdGVkKSB0aGVuIGEgIk5vQ2hhbmdlIiBldmVudCBzaG91bGQgaGF2ZSBiZWVuIGZpcmVkLgoJCUFzc2VydC5pc05vdE51bGwocmVzdWx0LCAibm8gc3RydWN0dXJlZERvY3VtZW50IGV2ZW50IHdhcyBjcmVhdGVkIGluIElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OnVwZGF0ZVN0cnVjdHVyZWREb2N1bWVudCIpOyAvLyROT04tTkxTLTEkCgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5kb2N1bWVudC5JRW5jb2RlZERvY3VtZW50I2dldFByZWZlcnJlZExpbmVEZWxpbWl0ZXIoKQoJICovCglwdWJsaWMgU3RyaW5nIGdldFByZWZlcnJlZExpbmVEZWxpbWl0ZXIoKSB7CgkJcmV0dXJuIGdldERlZmF1bHRMaW5lRGVsaW1pdGVyKCk7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZG9jdW1lbnQuSUVuY29kZWREb2N1bWVudCNzZXRQcmVmZXJyZWRMaW5lRGVsaW1pdGVyKGphdmEubGFuZy5TdHJpbmcpCgkgKi8KCXB1YmxpYyB2b2lkIHNldFByZWZlcnJlZExpbmVEZWxpbWl0ZXIoU3RyaW5nIHByb2JhYmxlTGluZURlbGltaXRlcikgewoJCXNldEluaXRpYWxMaW5lRGVsaW1pdGVyKHByb2JhYmxlTGluZURlbGltaXRlcik7CgoJfQoKCgkvKioKCSAqIENsYXNzIHdoaWNoIGltcGxlbWVudHMgdGhlIHJld3JpdGFibGUgc2Vzc2lvbiBmb3IgdGhlIFNTRS4KCSAqIAoJICovCgljbGFzcyBTdHJ1Y3R1cmVkRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBleHRlbmRzIERvY3VtZW50UmV3cml0ZVNlc3Npb24gewoKCQkvKioKCQkgKiBDcmVhdGVzIGEgbmV3IHNlc3Npb24uCgkJICogCgkJICogQHBhcmFtIHNlc3Npb25UeXBlCgkJICogICAgICAgICAgICB0aGUgdHlwZSBvZiB0aGlzIHNlc3Npb24KCQkgKi8KCQlwcm90ZWN0ZWQgU3RydWN0dXJlZERvY3VtZW50UmV3cml0ZVNlc3Npb24oRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUgc2Vzc2lvblR5cGUpIHsKCQkJc3VwZXIoc2Vzc2lvblR5cGUpOwoJCX0KCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNzdGFydFJld3JpdGVTZXNzaW9uKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUpCgkgKi8KCXB1YmxpYyBEb2N1bWVudFJld3JpdGVTZXNzaW9uIHN0YXJ0UmV3cml0ZVNlc3Npb24oRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUgc2Vzc2lvblR5cGUpIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24gewoJCS8vIGRlbGVnYXRlIHRvIHN1Yi1jbGFzcywgc28gVUkgdGhyZWFkaW5nIGlzIGhhbmRsZWQgY29ycmVjdGx5CgkJcmV0dXJuIGludGVybmFsU3RhcnRSZXdyaXRlU2Vzc2lvbihzZXNzaW9uVHlwZSk7Cgl9CgoJLyoqCgkgKiBOT1QtQVBJLiBGaW5hbCBwcm90ZWN0ZWQgc28gY2xpZW50cyBtYXkgY2FsbCB0aGlzIG1ldGhvZCBpZiBuZWVkZWQsIGJ1dAoJICogY2Fubm90IG92ZXJyaWRlLgoJICogCgkgKiBAcGFyYW0gc2Vzc2lvblR5cGUKCSAqIEByZXR1cm4KCSAqIEB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uCgkgKi8KCWZpbmFsIHByb3RlY3RlZCBEb2N1bWVudFJld3JpdGVTZXNzaW9uIGludGVybmFsU3RhcnRSZXdyaXRlU2Vzc2lvbihEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZSBzZXNzaW9uVHlwZSkgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiB7CgkJaWYgKGdldEFjdGl2ZVJld3JpdGVTZXNzaW9uKCkgIT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiYWxyZWFkeSBpbiBhIHJld3JpdGUgc2Vzc2lvbiIpOwoKCQlEb2N1bWVudFJld3JpdGVTZXNzaW9uIHNlc3Npb24gPSBuZXcgU3RydWN0dXJlZERvY3VtZW50UmV3cml0ZVNlc3Npb24oc2Vzc2lvblR5cGUpOwoJCURvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudCBldmVudCA9IG5ldyBEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQodGhpcywgc2Vzc2lvbiwgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50LlNFU1NJT05fU1RBUlQpOwoJCWZpcmVEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQoZXZlbnQpOwoKCQlJTGluZVRyYWNrZXIgdHJhY2tlciA9IGdldFRyYWNrZXIoKTsKCQlpZiAodHJhY2tlciBpbnN0YW5jZW9mIElMaW5lVHJhY2tlckV4dGVuc2lvbikgewoJCQlJTGluZVRyYWNrZXJFeHRlbnNpb24gZXh0ZW5zaW9uID0gKElMaW5lVHJhY2tlckV4dGVuc2lvbikgdHJhY2tlcjsKCQkJZXh0ZW5zaW9uLnN0YXJ0UmV3cml0ZVNlc3Npb24oc2Vzc2lvbik7CgkJfQoKCQlzdGFydFJld3JpdGVTZXNzaW9uT25QYXJ0aXRpb25lcnMoc2Vzc2lvbik7CgoJCWlmIChEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZS5TRVFVRU5USUFMID09IHNlc3Npb25UeXBlKQoJCQlzdGFydFNlcXVlbnRpYWxSZXdyaXRlKGZhbHNlKTsKCQllbHNlIGlmIChEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZS5TVFJJQ1RMWV9TRVFVRU5USUFMID09IHNlc3Npb25UeXBlKQoJCQlzdGFydFNlcXVlbnRpYWxSZXdyaXRlKHRydWUpOwoKCQlmQWN0aXZlUmV3cml0ZVNlc3Npb24gPSBzZXNzaW9uOwoJCXJldHVybiBzZXNzaW9uOwoJfQoKCS8qKgoJICogU3RhcnRzIHRoZSBnaXZlbiByZXdyaXRlIHNlc3Npb24uCgkgKgoJICogQHBhcmFtIHNlc3Npb24gdGhlIHJld3JpdGUgc2Vzc2lvbgoJICogQHNpbmNlIDIuMAoJICovCglmaW5hbCB2b2lkIHN0YXJ0UmV3cml0ZVNlc3Npb25PblBhcnRpdGlvbmVycyhEb2N1bWVudFJld3JpdGVTZXNzaW9uIHNlc3Npb24pIHsKCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzICE9IG51bGwpIHsKCQkJSXRlcmF0b3IgZT0gZkRvY3VtZW50UGFydGl0aW9uZXJzLnZhbHVlcygpLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChlLmhhc05leHQoKSkgewoJCQkJT2JqZWN0IHBhcnRpdGlvbmVyPSBlLm5leHQoKTsKCQkJCWlmIChwYXJ0aXRpb25lciBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMykgewoJCQkJCUlEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMyBleHRlbnNpb249IChJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjMpIHBhcnRpdGlvbmVyOwoJCQkJCWV4dGVuc2lvbi5zdGFydFJld3JpdGVTZXNzaW9uKHNlc3Npb24pOwoJCQkJfQoJCQl9CgkJfQoJfQoKCglwdWJsaWMgdm9pZCBzdG9wUmV3cml0ZVNlc3Npb24oRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBzZXNzaW9uKSB7CgkJLy8gZGVsZWdhdGUgdG8gc3ViLWNsYXNzLCBzbyBVSSB0aHJlYWRpbmcgaXMgaGFuZGxlZCBjb3JyZWN0bHkKCQlpbnRlcm5hbFN0b3BSZXdyaXRlU2Vzc2lvbihzZXNzaW9uKTsKCX0KCgkvKioKCSAqIE5PVC1BUEkuIEZpbmFsIHByb3RlY3RlZCBzbyBjbGllbnRzIG1heSBjYWxsIHRoaXMgbWV0aG9kIGlmIG5lZWRlZCwgYnV0CgkgKiBjYW5ub3Qgb3ZlcnJpZGUuCgkgKiAKCSAqIEBwYXJhbSBzZXNzaW9uCgkgKi8KCWZpbmFsIHByb3RlY3RlZCB2b2lkIGludGVybmFsU3RvcFJld3JpdGVTZXNzaW9uKERvY3VtZW50UmV3cml0ZVNlc3Npb24gc2Vzc2lvbikgewoJCWlmIChmQWN0aXZlUmV3cml0ZVNlc3Npb24gPT0gc2Vzc2lvbikgewoJCQlEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZSBzZXNzaW9uVHlwZSA9IHNlc3Npb24uZ2V0U2Vzc2lvblR5cGUoKTsKCQkJaWYgKERvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlLlNFUVVFTlRJQUwgPT0gc2Vzc2lvblR5cGUgfHwgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUuU1RSSUNUTFlfU0VRVUVOVElBTCA9PSBzZXNzaW9uVHlwZSkKCQkJCXN0b3BTZXF1ZW50aWFsUmV3cml0ZSgpOwoKCQkJc3RvcFJld3JpdGVTZXNzaW9uT25QYXJ0aXRpb25lcnMoc2Vzc2lvbik7CgoJCQlJTGluZVRyYWNrZXIgdHJhY2tlciA9IGdldFRyYWNrZXIoKTsKCQkJaWYgKHRyYWNrZXIgaW5zdGFuY2VvZiBJTGluZVRyYWNrZXJFeHRlbnNpb24pIHsKCQkJCUlMaW5lVHJhY2tlckV4dGVuc2lvbiBleHRlbnNpb24gPSAoSUxpbmVUcmFja2VyRXh0ZW5zaW9uKSB0cmFja2VyOwoJCQkJZXh0ZW5zaW9uLnN0b3BSZXdyaXRlU2Vzc2lvbihzZXNzaW9uLCBnZXQoKSk7CgkJCX0KCgkJCWZBY3RpdmVSZXdyaXRlU2Vzc2lvbiA9IG51bGw7CgkJCURvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudCBldmVudCA9IG5ldyBEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQodGhpcywgc2Vzc2lvbiwgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50LlNFU1NJT05fU1RPUCk7CgkJCWZpcmVEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQoZXZlbnQpOwoJCX0KCX0KCgkvKioKCSAqIFN0b3BzIHRoZSBnaXZlbiByZXdyaXRlIHNlc3Npb24uCgkgKgoJICogQHBhcmFtIHNlc3Npb24gdGhlIHJld3JpdGUgc2Vzc2lvbgoJICogQHNpbmNlIDIuMAoJICovCglmaW5hbCB2b2lkIHN0b3BSZXdyaXRlU2Vzc2lvbk9uUGFydGl0aW9uZXJzKERvY3VtZW50UmV3cml0ZVNlc3Npb24gc2Vzc2lvbikgewoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgIT0gbnVsbCkgewoJCQlEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWRFdmVudCBldmVudD0gbmV3IERvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZEV2ZW50KHRoaXMpOwoJCQlJdGVyYXRvciBlPSBmRG9jdW1lbnRQYXJ0aXRpb25lcnMua2V5U2V0KCkuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCQlTdHJpbmcgcGFydGl0aW9uaW5nPSAoU3RyaW5nKSBlLm5leHQoKTsKCQkJCUlEb2N1bWVudFBhcnRpdGlvbmVyIHBhcnRpdGlvbmVyPSAoSURvY3VtZW50UGFydGl0aW9uZXIpIGZEb2N1bWVudFBhcnRpdGlvbmVycy5nZXQocGFydGl0aW9uaW5nKTsKCQkJCWlmIChwYXJ0aXRpb25lciBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMykgewoJCQkJCUlEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMyBleHRlbnNpb249IChJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjMpIHBhcnRpdGlvbmVyOwoJCQkJCWV4dGVuc2lvbi5zdG9wUmV3cml0ZVNlc3Npb24oc2Vzc2lvbik7CgkJCQkJZXZlbnQuc2V0UGFydGl0aW9uQ2hhbmdlKHBhcnRpdGlvbmluZywgMCwgZ2V0TGVuZ3RoKCkpOwoJCQkJfQoJCQl9CgkJCWlmICghZXZlbnQuaXNFbXB0eSgpKQoJCQkJZmlyZURvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZChldmVudCk7CgkJfQoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I2dldEFjdGl2ZVJld3JpdGVTZXNzaW9uKCkKCSAqLwoJcHVibGljIERvY3VtZW50UmV3cml0ZVNlc3Npb24gZ2V0QWN0aXZlUmV3cml0ZVNlc3Npb24oKSB7CgkJcmV0dXJuIGZBY3RpdmVSZXdyaXRlU2Vzc2lvbjsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNhZGREb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIob3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCBhZGREb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIoSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgkJCUFzc2VydC5pc05vdE51bGwobGlzdGVuZXIpOwoJCQlpZiAoZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMgPT0gbnVsbCkgewoJCQkJZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMgPSBuZXcgQXJyYXlMaXN0KDEpOwoJCQl9CgkJCWlmICghZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMuY29udGFpbnMobGlzdGVuZXIpKQoJCQkJZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTsKCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjcmVtb3ZlRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKElEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJQXNzZXJ0LmlzTm90TnVsbChsaXN0ZW5lcik7CgkJCWlmIChmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycyAhPSBudWxsKQoJCQkJZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMucmVtb3ZlKGxpc3RlbmVyKTsKCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjcmVwbGFjZShpbnQsIGludCwKCSAqICAgICAgamF2YS5sYW5nLlN0cmluZywgbG9uZykKCSAqLwoJcHVibGljIHZvaWQgcmVwbGFjZShpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoLCBTdHJpbmcgdGV4dCwgbG9uZyBtb2RpZmljYXRpb25TdGFtcCkgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXBsYWNlVGV4dCh0aGlzLCBvZmZzZXQsIGxlbmd0aCwgdGV4dCwgbW9kaWZpY2F0aW9uU3RhbXAsIHRydWUpOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I3NldChqYXZhLmxhbmcuU3RyaW5nLAoJICogICAgICBsb25nKQoJICovCglwdWJsaWMgdm9pZCBzZXQoU3RyaW5nIHRleHQsIGxvbmcgbW9kaWZpY2F0aW9uU3RhbXApIHsKCQkvLyBidWcgMTUxMDY5IC0gb3ZlcndyaXRlIHJlYWQgb25seSByZWdpb25zIHdoZW4gc2V0dGluZyBlbnRpcmUgZG9jdW1lbnQKCQkgcmVwbGFjZVRleHQobnVsbCwgMCwgZ2V0TGVuZ3RoKCksIHRleHQsIG1vZGlmaWNhdGlvblN0YW1wLCB0cnVlKTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNnZXRNb2RpZmljYXRpb25TdGFtcCgpCgkgKi8KCXB1YmxpYyBsb25nIGdldE1vZGlmaWNhdGlvblN0YW1wKCkgewoJCXJldHVybiBmTW9kaWZpY2F0aW9uU3RhbXA7Cgl9CgkKCXByaXZhdGUgbG9uZyBnZXROZXh0TW9kaWZpY2F0aW9uU3RhbXAoKSB7CgkJaWYgKGZOZXh0TW9kaWZpY2F0aW9uU3RhbXAgPT0gTG9uZy5NQVhfVkFMVUUgfHwgZk5leHRNb2RpZmljYXRpb25TdGFtcCA9PSBJRG9jdW1lbnRFeHRlbnNpb240LlVOS05PV05fTU9ESUZJQ0FUSU9OX1NUQU1QKQoJCQlmTmV4dE1vZGlmaWNhdGlvblN0YW1wPSAwOwoJCWVsc2UKCQkJZk5leHRNb2RpZmljYXRpb25TdGFtcD0gZk5leHRNb2RpZmljYXRpb25TdGFtcCArIDE7CgoJCXJldHVybiBmTmV4dE1vZGlmaWNhdGlvblN0YW1wOwoJfQoKCS8qKgoJICogRmlyZXMgYW4gZXZlbnQsIGFzIHNwZWNpZmllZCwgdG8gdGhlIGFzc29jaWF0ZWQgbGlzdGVuZXJzLgoJICogCgkgKiBAcGFyYW0gZXZlbnQKCSAqICAgICAgICAgICAgVGhlIGV2ZW50IHRvIGZpcmUsIGVpdGhlciBhIHN0YXJ0IG9yIHN0b3AgZXZlbnQuCgkgKi8KCXByaXZhdGUgdm9pZCBmaXJlRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50KERvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudCBldmVudCkgewoJCWlmIChmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycyA9PSBudWxsIHx8IGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzLnNpemUoKSA9PSAwKQoJCQlyZXR1cm47CgoJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMpOwoJCUl0ZXJhdG9yIGUgPSBsaXN0Lml0ZXJhdG9yKCk7CgkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCUlEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIgbCA9IChJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKSBlLm5leHQoKTsKCQkJbC5kb2N1bWVudFJld3JpdGVTZXNzaW9uQ2hhbmdlZChldmVudCk7CgkJfQoJfQp9Cg==