LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAxLCAyMDA4IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gaW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqICAgICBKZW5zIEx1a293c2tpL0lubm9vcHJhY3QgLSBpbml0aWFsIHJlbmFtaW5nL3Jlc3RydWN0dXJpbmcKICogICAgIEplc3BlciBTdGVlbiBN+GxsZXIgLSBpbml0aWFsIElEb2N1bWVudEV4dGVuc2lvbjQgc3VwcG9ydCAtICMxMDI4MjIKICogICAgIAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwudGV4dDsKCmltcG9ydCBqYXZhLmlvLlJlYWRlcjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuUGxhdGZvcm07CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUucHJlZmVyZW5jZXMuSVNjb3BlQ29udGV4dDsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5wcmVmZXJlbmNlcy5JbnN0YW5jZVNjb3BlOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5EZWZhdWx0TGluZVRyYWNrZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50RXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZEV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5Eb2N1bWVudFJld3JpdGVTZXNzaW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5Eb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5GaW5kUmVwbGFjZURvY3VtZW50QWRhcHRlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50OwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjM7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudExpc3RlbmVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24zOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uMjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSUxpbmVUcmFja2VyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JTGluZVRyYWNrZXJFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklQb3NpdGlvblVwZGF0ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklSZWdpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklUZXh0U3RvcmU7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklUeXBlZFJlZ2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuUG9zaXRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LlNlcXVlbnRpYWxSZXdyaXRlVGV4dFN0b3JlOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5UeXBlZFJlZ2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5Mb2dnZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwuZG9jdW1lbnQuU3RydWN0dXJlZERvY3VtZW50RmFjdG9yeTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5lbmNvZGluZy5FbmNvZGluZ01lbWVudG87CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwubHRrLnBhcnNlci5SZWdpb25QYXJzZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLkFib3V0VG9CZUNoYW5nZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuSU1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmV2ZW50cy5JU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLk5vQ2hhbmdlRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLlJlZ2lvbkNoYW5nZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuUmVnaW9uc1JlcGxhY2VkRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLlN0cnVjdHVyZWREb2N1bWVudEV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmV2ZW50cy5TdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkRG9jdW1lbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZERvY3VtZW50UmVnaW9uOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLnRleHQuSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbkxpc3Q7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZFBhcnRpdGlvbmluZzsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkVGV4dFJlUGFyc2VyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnRleHQucnVsZXMuU3RydWN0dXJlZFRleHRQYXJ0aXRpb25lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51bmRvLklTdHJ1Y3R1cmVkVGV4dFVuZG9NYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnVuZG8uU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51dGlsLkFzc2VydDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51dGlsLkRlYnVnOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnV0aWwuVXRpbGl0aWVzOwoKCi8qKgogKiBUaGUgc3RhbmRhcmQgaW1wbGVtZW50YXRpb24gb2Ygc3RydWN0dXJlZCBkb2N1bWVudC4KICovCnB1YmxpYyBjbGFzcyBCYXNpY1N0cnVjdHVyZWREb2N1bWVudCBpbXBsZW1lbnRzIElTdHJ1Y3R1cmVkRG9jdW1lbnQsIElEb2N1bWVudEV4dGVuc2lvbiwgSURvY3VtZW50RXh0ZW5zaW9uMywgSURvY3VtZW50RXh0ZW5zaW9uNCwgQ2hhclNlcXVlbmNlLCBJUmVnaW9uQ29tcGFyaWJsZSB7CgoJLyoqCgkgKiBUaGlzIFRocmVhZExvY2FsIGNvbnN0cnVjdCBpcyB1c2VkIHNvIGVhY2ggdGhyZWFkIGNhbiBtYWludGFpbiBpdHMgb25seQoJICogcG9pbnRlciB0byB0aGUgZG91YmxlIGxpbmtlZCBsaXN0IHRoYXQgbWFuYWdlcyB0aGUgZG9jdW1lbnRzIHJlZ2lvbnMuCgkgKiBUaGUgb25seSB0aGluZyB3ZSAiZ2F1cmQiIGZvciBpcyB0aGF0IGEgcHJldmlvdXNseSBjYWNoZWQgcmVnaW9uIGhhcwoJICogYmVlbiBkZWxldGVkLgoJICogCgkgKiBUaGUgb2JqZWN0IHRoYXQgaXMga2VwdCBpbiB0aGUgdGhyZWFkIGxvY2FsJ3MgbWFwLCBpcyBqdXN0IGEgcG9pbnRlciB0bwoJICogYW4gYXJyYXkgcG9zaXRpb24uIFRoYXQncyBiZWNhdXNlIHRoZSBvYmplY3QgdGhlcmUgbmVlZHMgdG8gYmUgImZyZWUiCgkgKiBmcm9tIHJlZmVyZW5jZXMgdG8gb3RoZXIgb2JqZWN0cywgb3IgaXQgd2lsbCBub3QgYmUgZ2FyYmFnZSBjb2xsZWN0ZWQuCgkgKi8KCXByaXZhdGUgY2xhc3MgQ3VycmVudERvY3VtZW50UmVnaW9uQ2FjaGUgewoJCS8vIEknbSBhc3N1bWluZyBmb3Igbm93IHRoZXJlIHdvdWxkIG5ldmVyIGJlIHNvIG1hbnkgdGhyZWFkcyB0aGF0CgkJLy8gdGhpcyBhcnJheUxpc3QgbmVlZHMgdG8gYmUgYm91bmRlZCwgb3IgJ2NsZWFuZWQgdXAnLgoJCS8vIHRoaXMgYXNzdW1wdGlvbiBzaG91bGQgYmUgdGVzdGVkIGluIHByYWN0aWNlIGFuZCBsb25nIHJ1bm5pbmcKCQkvLyBqb2JzIC0tIGZvdW5kIG5vdCB0byBiZSBhIGdvb2QgYXNzdW1wdGlvbi4gU2VlIGJlbG93LgoJCXByaXZhdGUgTGlzdCBjYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5ID0gQ29sbGVjdGlvbnMuc3luY2hyb25pemVkTGlzdChuZXcgQXJyYXlMaXN0KCkpOwoJCXByaXZhdGUgZmluYWwgYm9vbGVhbiBERUJVRyA9IGZhbHNlOwoJCXByaXZhdGUgZmluYWwgaW50IE1BWF9TSVpFID0gNTA7CgoKCQlwcml2YXRlIFRocmVhZExvY2FsIHRocmVhZExvY2FsQ2FjaGVQb3NpdGlvbiA9IG5ldyBUaHJlYWRMb2NhbCgpOwoKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGdldCgpIHsKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24gPSBudWxsOwoJCQlpbnQgcG9zID0gZ2V0VGhyZWFkTG9jYWxQb3NpdGlvbigpOwoJCQl0cnkgewoJCQkJcmVnaW9uID0gKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24pIGNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuZ2V0KHBvcyk7CgkJCX0KCQkJY2F0Y2ggKEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gZSkgewoJCQkJLy8gZXZlbiB0aG91Z2ggdGhlIGNhY2hlZFJlZ2lvblBvc2l0aW9uIGlzIHN5bmNocm9uaXplZCwKCQkJCS8vIHRoYXQganVzdCBtZWFucyBlYWNoIGFjY2VzcyBpcyBzeW5jcm9uaXplZCwgaXRzCgkJCQkvLyBzdGlsbCBwb3NzaWJsZSBmb3IgYW5vdGhlciB0aHJlYWQgdG8gY2F1c2UgaXQgdG8KCQkJCS8vIGJlIGNsZWFyZWQsIGFmdGVyIHRoaXMgdGhyZWFkIGdldHMgaXQgcG9zaXRpb24uCgkJCQkvLyBTbywgaWYgdGhhdCBoYXBwZW5zLCBhbGwgd2UgY2FuIGRvIGlzIHJlc2V0IHRvIGJlZ2lubmluZy4KCQkJCS8vIFRoaXMgc2hvdWxkIGJlIGV4dHJlbWVseSByYXJlIChpbiBvdGhlciB3b3JkcywgcHJvYmFibHkKCQkJCS8vIG5vdCB3b3J0aCB1c2luZyBzeW5jaHJvbml6ZWQgYmxvY2tzCgkJCQkvLyB0byBhY2Nlc3MgY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS4KCQkJCXJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJCXJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCQlpZiAocmVnaW9uID09IG51bGwpIHsKCQkJCXJlZ2lvbiA9IHJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCQllbHNlCgkJCS8vIHJlZ2lvbiBub3QgbnVsbAoJCQlpZiAocmVnaW9uLmlzRGVsZXRlZCgpKSB7CgkJCQlyZWdpb24gPSByZXNldFRvSW5pdGlhbFN0YXRlKCk7CgkJCX0KCQkJcmV0dXJuIHJlZ2lvbjsKCQl9CgoJCXByaXZhdGUgaW50IGdldFRocmVhZExvY2FsUG9zaXRpb24oKSB7CgkJCU9iamVjdCB0aHJlYWRMb2NhbE9iamVjdCA9IHRocmVhZExvY2FsQ2FjaGVQb3NpdGlvbi5nZXQoKTsKCQkJaW50IHBvcyA9IC0xOwoJCQlpZiAodGhyZWFkTG9jYWxPYmplY3QgPT0gbnVsbCkgewoKCQkJCXBvcyA9IHJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJfQoJCQllbHNlIHsKCQkJCXBvcyA9ICgoSW50ZWdlcikgdGhyZWFkTG9jYWxPYmplY3QpLmludFZhbHVlKCk7CgkJCX0KCQkJcmV0dXJuIHBvczsKCQl9CgoJCS8qKgoJCSAqIEByZXR1cm4KCQkgKi8KCQlwcml2YXRlIGludCByZWluaXRUaHJlYWRMb2NhbFBvc2l0aW9uKCkgewoJCQlJbnRlZ2VyIHBvc2l0aW9uOwoJCQlpbnQgcG9zOwoJCQkvLyBUT0RPX2Z1dHVyZTogdGhpbmsgb2YgYSBiZXR0ZXIgc29sdXRpb24gdGhhdCBkb2Vzbid0CgkJCS8vIHJlcXVpcmUgdGhpcyBrbHVkZ2UuIFRoaXMgaXMgZXNwZWNpYWxseSByZXF1aXJlZCBiZWNhdXNlCgkJCS8vIHNvbWUgaW5mcmFzdHVyZSwgc3VjaCBhcyByZWNvbmNpbGVyLCBhY3R1YWxseSBudWxsIG91dAoJCQkvLyB0aGVpciB0aHJlYWQgb2JqZWN0IGFuZCByZWNyZWF0ZSBpdCwgNTAwIG1zZWNzIGxhdGVyCgkJCS8vIChhcHByb3hpbWF0ZWx5KS4KCQkJLy8gTm90ZTogdGhlIGxpa2VseSBzb2x1dGlvbiBpbiBmdXR1cmUgaXMgdG8gY2xlYXIgYWZ0ZXIgZXZlcnkKCQkJLy8gaGVhdnkgdXNlIG9mIGdldENhY2hlZFJlZ2lvbiwgc3VjaCBhcyBpbiBjcmVhdGluZyBub2RlCgkJCS8vIGxpc3RzLCBvciByZXBhcnNpbmcgb3IgcGFydGlvbmluZy4KCQkJaWYgKGNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuc2l6ZSgpID4gTUFYX1NJWkUpIHsKCQkJCWNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuY2xlYXIoKTsKCQkJCWlmIChERUJVRykgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheSBjbGVhcmVkIGF0IHNpemUgIiArIE1BWF9TSVpFKTsgLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJCXBvc2l0aW9uID0gbmV3IEludGVnZXIoY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5zaXplKCkpOwoJCQl0aHJlYWRMb2NhbENhY2hlUG9zaXRpb24uc2V0KHBvc2l0aW9uKTsKCQkJY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5hZGQocG9zaXRpb24uaW50VmFsdWUoKSwgbnVsbCk7CgkJCXBvcyA9IHBvc2l0aW9uLmludFZhbHVlKCk7CgkJCXJldHVybiBwb3M7CgkJfQoKCQlwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVzZXRUb0luaXRpYWxTdGF0ZSgpIHsKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb247CgkJCXJlZ2lvbiA9IGdldEZpcnN0U3RydWN0dXJlZERvY3VtZW50UmVnaW9uKCk7CgkJCXNldChyZWdpb24pOwoJCQlyZXR1cm4gcmVnaW9uOwoJCX0KCgkJLy8gVE9ETzogbWFrZSBwcml2aXRlIGlmIHVzZWQsIGVsc2UgZGVsZXRlCgkJdm9pZCBzZXQoaW50IHBvcywgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24pIHsKCQkJY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5zZXQocG9zLCByZWdpb24pOwoJCX0KCgkJdm9pZCBzZXQoSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24pIHsKCQkJdHJ5IHsKCQkJCWludCBwb3MgPSBnZXRUaHJlYWRMb2NhbFBvc2l0aW9uKCk7CgkJCQljYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5LnNldChwb3MsIHJlZ2lvbik7CgkJCX0KCQkJY2F0Y2ggKEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gZSkgewoJCQkJLy8gZXZlbiB0aG91Z2ggdGhlIGNhY2hlZFJlZ2lvblBvc2l0aW9uIGlzIHN5bmNocm9uaXplZCwKCQkJCS8vIHRoYXQganVzdCBtZWFucyBlYWNoIGFjY2VzcyBpcyBzeW5jcm9uaXplZCwgaXRzCgkJCQkvLyBzdGlsbCBwb3NzaWJsZSBmb3IgYW5vdGhlciB0aHJlYWQgdG8gY2F1c2UgaXQgdG8KCQkJCS8vIGJlIGNsZWFyZWQsIGFmdGVyIHRoaXMgdGhyZWFkIGdldHMgaXQgcG9zaXRpb24uCgkJCQkvLyBTbywgaWYgdGhhdCBoYXBwZW5zLCBhbGwgd2UgY2FuIGRvIGlzIHJlc2V0IHRvIGJlZ2lubmluZy4KCQkJCS8vIFRoaXMgc2hvdWxkIGJlIGV4dHJlbWVseSByYXJlIChpbiBvdGhlciB3b3JkcywgcHJvYmFibHkKCQkJCS8vIG5vdCB3b3J0aCB1c2luZyBzeW5jaHJvbml6ZWQgYmxvY2tzCgkJCQkvLyB0byBhY2Nlc3MgY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS4KCQkJCXJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJCXJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCX0KCX0KCgkvKioKCSAqIFRoaXMgTnVsbERvY3VtZW50RXZlbnQgaXMgdXNlZCB0byBjb21wbGV0ZSB0aGUgImFib3V0VG9DaGFuZ2UiIGFuZAoJICogImNoYW5nZWQiIGN5Y2xlLCB3aGVuIGluIGZhY3QgdGhlIG9yaWdpbmFsIGNoYW5nZSBpcyBubyBsb25nZXIgdmFsaWQuCgkgKiBUaGUgb25seSBrbm93biAodmFsaWQpIGNhc2Ugb2YgdGhpcyBpcyB3aGVuIGEgbW9kZWwgcmUtaW5pdGlhbGl6ZSB0YWtlcwoJICogcGxhY2UsIHdoaWNoIGNhdXNlcyBzZXRUZXh0IHRvIGJlIGNhbGxlZCBpbiB0aGUgbWlkZGxlIG9mIHNvbWUgcHJldmlvdXMKCSAqIGNoYW5nZS4gW1RoaXMgYXJjaGl0ZWN0dXJlIHdpbGwgYmUgaW1wcm92ZWQgaW4gZnV0dXJlXS4KCSAqLwoJcHVibGljIGNsYXNzIE51bGxEb2N1bWVudEV2ZW50IGV4dGVuZHMgRG9jdW1lbnRFdmVudCB7CgkJcHVibGljIE51bGxEb2N1bWVudEV2ZW50KCkgewoJCQl0aGlzKEJhc2ljU3RydWN0dXJlZERvY3VtZW50LnRoaXMsIDAsIDAsICIiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJcHJpdmF0ZSBOdWxsRG9jdW1lbnRFdmVudChJRG9jdW1lbnQgZG9jLCBpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoLCBTdHJpbmcgdGV4dCkgewoJCQlzdXBlcihkb2MsIG9mZnNldCwgbGVuZ3RoLCB0ZXh0KTsKCQl9Cgl9CgoJY2xhc3MgUmVnaXN0ZXJlZFJlcGxhY2UgewoJCS8qKiBUaGUgb3duZXIgb2YgdGhpcyByZXBsYWNlIG9wZXJhdGlvbi4gKi8KCQlJRG9jdW1lbnRMaXN0ZW5lciBmT3duZXI7CgkJLyoqIFRoZSByZXBsYWNlIG9wZXJhdGlvbiAqLwoJCUlEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSBmUmVwbGFjZTsKCgkJLyoqCgkJICogQ3JlYXRlcyBhIG5ldyBidW5kbGUgb2JqZWN0LgoJCSAqIAoJCSAqIEBwYXJhbSBvd25lcgoJCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50IGxpc3RlbmVyIG93bmluZyB0aGUgcmVwbGFjZSBvcGVyYXRpb24KCQkgKiBAcGFyYW0gcmVwbGFjZQoJCSAqICAgICAgICAgICAgdGhlIHJlcGxhY2Ugb3BlcmF0aW9uCgkJICovCgkJUmVnaXN0ZXJlZFJlcGxhY2UoSURvY3VtZW50TGlzdGVuZXIgb3duZXIsIElEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSByZXBsYWNlKSB7CgkJCWZPd25lciA9IG93bmVyOwoJCQlmUmVwbGFjZSA9IHJlcGxhY2U7CgkJfQoJfQoKCS8qKgoJICogdGhlc2UgY29udHJvbCB2YXJpYWJsZSBpc24ndCBtYXJrIGFzICdmaW5hbCcgc2luY2UgdGhlcmUncyBzb21lIHVuaXQKCSAqIHRlc3RzIHRoYXQgbWFuaXB1bGF0ZSBpdC4gRm9yIGZpbmFsIHByb2R1Y3QsIGl0IHNob3VsZCBiZS4KCSAqLwoKCXByaXZhdGUgc3RhdGljIGJvb2xlYW4gVVNFX0xPQ0FMX1RIUkVBRCA9IHRydWU7CgoJLyoqCgkgKiBwdXJlbHkgZm9yIGRlYnVnZ2luZy9wZXJmb3JtYW5jZSBtZWFzdXJlbWVudHMgSW4gcHJhY3RpY2UsIHdvdWxkIGFsd2F5cwoJICogYmUgJ3RydWUnLiAoYW5kIHNob3VsZCBuZXZlciBiZSBjYWxsZWQgYnkgY2FsbGVkIGJ5IGNsaWVudHMpLiBJdHMgbm90CgkgKiAnZmluYWwnIG9yIHByaXZhdGUganVzdCBzbyBpdCBjYW4gYmUgdmFyaWVkIGR1cmluZwoJICogZGVidWdnaW5nL3BlcmZvcm1hbmNlIG1lYXN1cmVtZW50IHJ1bnMuCgkgKiAKCSAqIEBwYXJhbSB1c2VfbG9jYWxfdGhyZWFkCgkgKi8KCXB1YmxpYyBzdGF0aWMgdm9pZCBzZXRVU0VfTE9DQUxfVEhSRUFEKGZpbmFsIGJvb2xlYW4gdXNlX2xvY2FsX3RocmVhZCkgewoJCVVTRV9MT0NBTF9USFJFQUQgPSB1c2VfbG9jYWxfdGhyZWFkOwoJfQoKCXByaXZhdGUgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBjYWNoZWREb2N1bWVudFJlZ2lvbjsKCXByaXZhdGUgRW5jb2RpbmdNZW1lbnRvIGVuY29kaW5nTWVtZW50bzsKCXByaXZhdGUgYm9vbGVhbiBmQWNjZXB0UG9zdE5vdGlmaWNhdGlvblJlcGxhY2VzID0gdHJ1ZTsKCXByaXZhdGUgQ3VycmVudERvY3VtZW50UmVnaW9uQ2FjaGUgZkN1cnJlbnREb2N1bW5ldFJlZ2lvbkNhY2hlOwoJcHJpdmF0ZSBEb2N1bWVudEV2ZW50IGZEb2N1bWVudEV2ZW50OwoJcHJpdmF0ZSBJRG9jdW1lbnRMaXN0ZW5lcltdIGZEb2N1bWVudExpc3RlbmVyczsKCgkvKioKCSAqIFRoZSByZWdpc3RlcmVkIGRvY3VtZW50IHBhcnRpdGlvbmVycy4KCSAqLwoJcHJpdmF0ZSBNYXAgZkRvY3VtZW50UGFydGl0aW9uZXJzOwoJLyoqIFRoZSByZWdpc3RlcmVkIGRvY3VtZW50IHBhcnRpdGlvbmluZyBsaXN0ZW5lcnMgKi8KCXByaXZhdGUgTGlzdCBmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnM7Cglwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZmlyc3REb2N1bWVudFJlZ2lvbjsKCXByaXZhdGUgUmVnaW9uUGFyc2VyIGZQYXJzZXI7Cglwcml2YXRlIEdlbmVyaWNQb3NpdGlvbk1hbmFnZXIgZlBvc2l0aW9uTWFuYWdlcjsKCXByaXZhdGUgTGlzdCBmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXM7Cglwcml2YXRlIElEb2N1bWVudExpc3RlbmVyW10gZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnM7Cglwcml2YXRlIGludCBmUmVlbnRyYW5jZUNvdW50ID0gMDsKCXByaXZhdGUgSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgZlJlUGFyc2VyOwoJcHJpdmF0ZSBpbnQgZlN0b3BwZWRDb3VudCA9IDA7CgoJcHJpdmF0ZSBJVGV4dFN0b3JlIGZTdG9yZTsKCXByaXZhdGUgT2JqZWN0W10gZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnM7Cglwcml2YXRlIE9iamVjdFtdIGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzOwoJcHJpdmF0ZSBPYmplY3RbXSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnM7CgoJcHJpdmF0ZSBMaXN0IGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzOwoKCXByaXZhdGUgSUxpbmVUcmFja2VyIGZUcmFja2VyOwoJcHJpdmF0ZSBJU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlciBmVW5kb01hbmFnZXI7Cglwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gbGFzdERvY3VtZW50UmVnaW9uOwoKCXByaXZhdGUgYnl0ZVtdIGxpc3RlbmVyTG9jayA9IG5ldyBieXRlWzBdOwoJcHJpdmF0ZSBOdWxsRG9jdW1lbnRFdmVudCBOVUxMX0RPQ1VNRU5UX0VWRU5UOwoKCS8qKgoJICogVGhlb3JldGljYWxseSwgYSBkb2N1bWVudCBjYW4gY29udGFpbiBtaXhlZCBsaW5lIGRlbGltaXRlcnMsIGJ1dCB0aGUKCSAqIHVzZXIncyBwcmVmZXJlbmNlIGlzIHVzdWFsbHkgdG8gYmUgaW50ZXJuYWxseSBjb25zaXN0ZW50LgoJICovCglwcml2YXRlIFN0cmluZyBmSW5pdGlhbExpbmVEZWxpbWl0ZXI7Cglwcml2YXRlIGZpbmFsIFN0cmluZyBSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSA9ICJfUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUllfIjsgLy8kTk9OLU5MUy0xJAoJLyoqCgkgKiBDdXJyZW50IHJld3JpdGUgc2Vzc2lvbiwgb3Igbm9uZSBpZiBub3QgcHJlc2VudGx5IHJld3JpdGluZy4KCSAqLwoJcHJpdmF0ZSBEb2N1bWVudFJld3JpdGVTZXNzaW9uIGZBY3RpdmVSZXdyaXRlU2Vzc2lvbjsKCS8qKgoJICogTGFzdCBtb2RpZmljYXRpb24gc3RhbXAsIGF1dG9tYXRpY2FsbHkgdXBkYXRlZCBvbiBjaGFuZ2UuCgkgKi8KCXByaXZhdGUgbG9uZyBmTW9kaWZpY2F0aW9uU3RhbXA7CgkvKioKCSAqIEtlZXBzIHRyYWNrIG9mIG5leHQgbW9kaWZpY2F0aW9uIHN0YW1wLgoJICovCglwcml2YXRlIGxvbmcgZk5leHRNb2RpZmljYXRpb25TdGFtcD0gSURvY3VtZW50RXh0ZW5zaW9uNC5VTktOT1dOX01PRElGSUNBVElPTl9TVEFNUDsKCS8qKgoJICogZGVidWcgdmFyaWFibGUgb25seQoJICogCgkgKiBAcGFyYW0gcGFyc2VyCgkgKi8KCXByaXZhdGUgbG9uZyBzdGFydFN0cmVhbVRpbWU7CgkvKioKCSAqIGRlYnVnIHZhcmlhYmxlIG9ubHkKCSAqIAoJICogQHBhcmFtIHBhcnNlcgoJICovCglwcml2YXRlIGxvbmcgc3RhcnRUaW1lOwoKCXB1YmxpYyBCYXNpY1N0cnVjdHVyZWREb2N1bWVudCgpIHsKCQlzdXBlcigpOwoJCWZDdXJyZW50RG9jdW1uZXRSZWdpb25DYWNoZSA9IG5ldyBDdXJyZW50RG9jdW1lbnRSZWdpb25DYWNoZSgpOwoJCWZTdG9yZSA9IG5ldyBTdHJ1Y3R1cmVkRG9jdW1lbnRUZXh0U3RvcmUoNTAsIDMwMCk7CgkJc2V0TGluZVRyYWNrZXIobmV3IERlZmF1bHRMaW5lVHJhY2tlcigpKTsKCQlOVUxMX0RPQ1VNRU5UX0VWRU5UID0gbmV3IE51bGxEb2N1bWVudEV2ZW50KCk7CgoJCWludGVybmFsX2FkZFBvc2l0aW9uQ2F0ZWdvcnkoUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlkpOwoJCWludGVybmFsX2FkZFBvc2l0aW9uVXBkYXRlcihuZXcgRGVsZXRlRXF1YWxQb3NpdGlvblVwZGF0ZXIoUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlkpKTsKCgl9CgoJLyoqCgkgKiBUaGlzIGlzIHRoZSBwcmltYXJ5IHdheSB0byBnZXQgYSBuZXcgc3RydWN0dXJlZERvY3VtZW50LiBJdHMgYmVzdCB0bwoJICogdXNlIHRoZSBmYWN0b3J5IG1ldGhvZHMgaW4gTW9kZWxNYW5nZXIgdG8gY3JlYXRlIGEgbmV3CgkgKiBJU3RydWN0dXJlZERvY3VtZW50LCBzaW5jZSBpdCB3aWxsIGdldCBhbmQgaW5pdGlhbGl6ZSB0aGUgcGFyc2VyCgkgKiBhY2NvcmRpbmcgdG8gdGhlIGRlc2lyZWQgY29udGVudCB0eXBlLgoJICovCglwdWJsaWMgQmFzaWNTdHJ1Y3R1cmVkRG9jdW1lbnQoUmVnaW9uUGFyc2VyIHBhcnNlcikgewoJCXRoaXMoKTsKCQlBc3NlcnQuaXNOb3ROdWxsKHBhcnNlciwgIlByb2dyYW0gRXJyb3I6IElTdHJ1Y3R1cmVkRG9jdW1lbnQgY2FuIG5vdCBiZSBjcmVhdGVkIHdpdGggbnVsbCBwYXJzZXIiKTsgLy8kTk9OLU5MUy0xJAoJCS8vIGdvIHRocm91Z2ggc2V0dGVyIGluIGNhc2UgdGhlcmUgaXMgc2lkZSBlZmZlY3RzCgkJaW50ZXJuYWxfc2V0UGFyc2VyKHBhcnNlcik7Cgl9CgoJcHJpdmF0ZSB2b2lkIF9jbGVhckRvY3VtZW50RXZlbnQoKSB7CgkJLy8gbm8gaGFyZCBhbmQgZmFzdCByZXF1aXJlbWVudCB0byBudWxsIG91dCAuLi4ganVzdCBzZWVtcyBsaWtlCgkJLy8gYSBnb29kIGlkZWEsIHNpbmNlIHdlIGFyZSBkb25lIHdpdGggaXQuCgkJZkRvY3VtZW50RXZlbnQgPSBudWxsOwoJfQoKCXByaXZhdGUgdm9pZCBfZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZShPYmplY3RbXSBsaXN0ZW5lcnMpIHsKCQkvLyBtb3N0IERvY3VtZW50QWJvdXRUb0JlQ2hhbmdlZCBsaXN0ZW5lcnMgZG8gbm90IGFudGljaXBhdGUKCQkvLyBEb2N1bWVudEV2ZW50ID09IG51bGwuIFNvIG1ha2Ugc3VyZSBkb2N1bWVudEV2ZW50IGlzIG5vdAoJCS8vIG51bGwuICh0aGlzIHNob3VsZCBuZXZlciBoYXBwZW4sIHlldCBpdCBkb2VzIHNvbWV0aW1lcykKCQlpZiAoZkRvY3VtZW50RXZlbnQgPT0gbnVsbCkgewoJCQlmRG9jdW1lbnRFdmVudCA9IG5ldyBOdWxsRG9jdW1lbnRFdmVudCgpOwoJCX0KCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJLy8gTm90ZTogdGhlIGRvY0V2ZW50IGlzIGNyZWF0ZWQgaW4gcmVwbGFjZVRleHQgQVBJCgkJCS8vIGZpcmUKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBob2xkTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlzdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCX0KCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCSgoSURvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLmRvY3VtZW50QWJvdXRUb0JlQ2hhbmdlZChmRG9jdW1lbnRFdmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCWxvbmcgc3RvcFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgSVN0cnVjdHVyZWREb2N1bWVudDo6ZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50LiBUaW1lIHdhcyAiICsgKHN0b3BUaW1lIC0gc3RhcnRUaW1lKSArICIgbXNlY3MgdG8gZmlyZSBOZXdNb2RlbEV2ZW50IHRvIGluc3RhbmNlIG9mICIgKyBob2xkTGlzdGVuZXJzW2ldLmdldENsYXNzKCkpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0Fib3V0VG9DaGFuZ2UoRG9jdW1lbnRFdmVudCBkb2N1bWVudEV2ZW50KSB7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyAhPSBudWxsKSB7CgkJCUl0ZXJhdG9yIGUgPSBmRG9jdW1lbnRQYXJ0aXRpb25lcnMudmFsdWVzKCkuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwID0gKElEb2N1bWVudFBhcnRpdGlvbmVyKSBlLm5leHQoKTsKCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJcC5kb2N1bWVudEFib3V0VG9CZUNoYW5nZWQoZG9jdW1lbnRFdmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVEb2N1bWVudENoYW5nZWQoT2JqZWN0W10gbGlzdGVuZXJzLCBTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCBldmVudCkgewoKCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJLy8gTk9URTogZG9jdW1lbnQgZXZlbnQgaXMgY3JlYXRlZCBpbiByZXBsYWNlIFRleHQgQVBJIGFuZCBzZXRUZXh0CgkJCS8vIEFQSQoJCQkvLyBub3cgZmlyZQoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoKCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCS8vIE5vdGVzOiBmRG9jdW1lbnRFdmVudCBjYW4gYmUgInN1ZGRlbmx5IiBudWxsLCBpZiBvbmUgb2YKCQkJCQkvLyB0aGUKCQkJCQkvLyBwcmV2aW91cyBjaGFuZ2VzCgkJCQkJLy8gY2F1c2VkIGEgInNldFRleHQiIHRvIGJlIGNhbGxlZC4gVGhlIG9ubHkga25vd24gY2FzZSBvZgoJCQkJCS8vIHRoaXMKCQkJCQkvLyBpcyBhIG1vZGVsIHJlc2V0CgkJCQkJLy8gZHVlIHRvIHBhZ2UgZGlyZWN0aXZlIGNoYW5naW5nLiBFdmVudHVhbGx5IHdlIHNob3VsZAoJCQkJCS8vIGNoYW5nZQoJCQkJCS8vIGFyY2hldGVjdHVyZSB0byBoYXZlCgkJCQkJLy8gZXZlbnQgcXVlIGFuZCBiZSBhYmxlIHRvICJjYW5jZWwiIHBlbmRpbmcgZXZlbnRzLCBidXQKCQkJCQkvLyBmb3IKCQkJCQkvLyBub3csIHdlJ2xsIGp1c3QgcGFzcyBhCgkJCQkJLy8gTnVsbERvY3VtZW50RXZlbnQuIEJ5IHRoZSB3YXksIGl0IGlzIGltcG9ydGFudCB0byBzZW5kCgkJCQkJLy8gc29tZXRoaW5nLCBzaW5jZSBjbGllbnRzIG1pZ2h0CgkJCQkJLy8gaGF2ZSBpbmRldGVybWluYW50IHN0YXRlIGR1ZSB0byAiYWJvdXRUb0NoYW5nZSIgYmVpbmcKCQkJCQkvLyBzZW50CgkJCQkJLy8gZWFybGllci4KCQkJCQlpZiAoZkRvY3VtZW50RXZlbnQgPT0gbnVsbCkgewoJCQkJCQkoKElEb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5kb2N1bWVudENoYW5nZWQoTlVMTF9ET0NVTUVOVF9FVkVOVCk7CgkJCQkJfQoJCQkJCWVsc2UgewoJCQkJCQlmRG9jdW1lbnRFdmVudC5mTW9kaWZpY2F0aW9uU3RhbXAgPSBnZXRNb2RpZmljYXRpb25TdGFtcCgpOwoJCQkJCQkoKElEb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5kb2N1bWVudENoYW5nZWQoZkRvY3VtZW50RXZlbnQpOwoJCQkJCX0KCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIG5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzRG9jdW1lbnRDaGFuZ2VkKERvY3VtZW50RXZlbnQgZG9jdW1lbnRFdmVudCkgewoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgIT0gbnVsbCkgewoJCQlJdGVyYXRvciBlID0gZkRvY3VtZW50UGFydGl0aW9uZXJzLnZhbHVlcygpLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChlLmhhc05leHQoKSkgewoJCQkJSURvY3VtZW50UGFydGl0aW9uZXIgcCA9IChJRG9jdW1lbnRQYXJ0aXRpb25lcikgZS5uZXh0KCk7CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCWlmIChwIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24pIHsKCQkJCQkJLy8gSVJlZ2lvbiBjaGFuZ2VkUGFydGlvbiA9CgkJCQkJCSgoSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24pIHApLmRvY3VtZW50Q2hhbmdlZDIoZG9jdW1lbnRFdmVudCk7CgkJCQkJfQoJCQkJCWVsc2UgewoJCQkJCQlwLmRvY3VtZW50Q2hhbmdlZChkb2N1bWVudEV2ZW50KTsKCQkJCQl9CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJfQoJCX0KCX0KCgoJcHJpdmF0ZSB2b2lkIF9maXJlRXZlbnQoT2JqZWN0W10gbGlzdGVuZXJzLCBOb0NoYW5nZUV2ZW50IGV2ZW50KSB7CgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkoKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkubm9DaGFuZ2UoZXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVFdmVudChPYmplY3RbXSBsaXN0ZW5lcnMsIFJlZ2lvbkNoYW5nZWRFdmVudCBldmVudCkgewoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJKChJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLnJlZ2lvbkNoYW5nZWQoZXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVFdmVudChPYmplY3RbXSBsaXN0ZW5lcnMsIFJlZ2lvbnNSZXBsYWNlZEV2ZW50IGV2ZW50KSB7CgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkoKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkucmVnaW9uc1JlcGxhY2VkKGV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIF9maXJlRXZlbnQoT2JqZWN0W10gbGlzdGVuZXJzLCBTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCBldmVudCkgewoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJKChJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLm5vZGVzUmVwbGFjZWQoZXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlKE9iamVjdFtdIGxpc3RlbmVycykgewoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQkvLyBOb3RlOiB0aGUgZG9jRXZlbnQgaXMgY3JlYXRlZCBpbiByZXBsYWNlVGV4dCBBUEkKCQkJLy8gZmlyZQoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyBub3RpY2UgdGhlIEFib3V0VG9CZUNoYW5nZWRFdmVudCBpcyBjcmVhdGVkIGZyb20gdGhlCgkJCQkJLy8gRG9jdW1lbnRFdmVudCwgc2luY2UgaXQgaXMgKG5lYXJseSkKCQkJCQkvLyB0aGUgc2FtZSBpbmZvcm1hdGlvbi4gP1doYXQgdG8gZG8gYWJvdXQKCQkJCQkvLyBvcmlnaW5hbFJlcXVlc3Rlcj8KCQkJCQlpZiAoZkRvY3VtZW50RXZlbnQgPT0gbnVsbCkgewoJCQkJCQlmRG9jdW1lbnRFdmVudCA9IG5ldyBOdWxsRG9jdW1lbnRFdmVudCgpOwoJCQkJCX0KCQkJCQlBYm91dFRvQmVDaGFuZ2VkRXZlbnQgYWJvdXRUb0JlQ2hhbmdlZEV2ZW50ID0gbmV3IEFib3V0VG9CZUNoYW5nZWRFdmVudCh0aGlzLCBudWxsLCBmRG9jdW1lbnRFdmVudC5nZXRUZXh0KCksIGZEb2N1bWVudEV2ZW50LmdldE9mZnNldCgpLCBmRG9jdW1lbnRFdmVudC5nZXRMZW5ndGgoKSk7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCSgoSU1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5tb2RlbEFib3V0VG9CZUNoYW5nZWQoYWJvdXRUb0JlQ2hhbmdlZEV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJvdGVjdGVkIHZvaWQgYWNxdWlyZUxvY2soKSB7CgkJLy8gZG8gbm90aGluZyBoZXJlIGluIHN1cGVyIGNsYXNzCgl9CgoJLyoqCgkgKiBhZGRNb2RlbEFib3V0VG9CZUNoYW5nZWRMaXN0ZW5lciBtZXRob2QgY29tbWVudC4KCSAqLwoJcHVibGljIHZvaWQgYWRkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXIoSU1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCS8vIG1ha2Ugc3VyZSBsaXN0ZW5lciBpcyBub3QgYWxyZWFkeSBpbiBsaXN0ZW5pbmcKCQkJLy8gKGFuZCBpZiBpdCBpcywgcHJpbnQgYSB3YXJuaW5nIHRvIGFpZCBkZWJ1Z2dpbmcsIGlmIG5lZWRlZCkKCQkJaWYgKCFVdGlsaXRpZXMuY29udGFpbnMoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJaW50IG9sZFNpemUgPSAwOwoJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQkvLyBub3JtYWxseSB3b24ndCBiZSBudWxsLCBidXQgd2UgbmVlZCB0byBiZSBzdXJlLCBmb3IKCQkJCQkvLyBmaXJzdAoJCQkJCS8vIHRpbWUgdGhyb3VnaAoJCQkJCW9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycy5sZW5ndGg7CgkJCQl9CgkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgKyAxOwoJCQkJT2JqZWN0W10gbmV3TGlzdGVuZXJzID0gbmV3IE9iamVjdFtuZXdTaXplXTsKCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJU3lzdGVtLmFycmF5Y29weShmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycywgMCwgbmV3TGlzdGVuZXJzLCAwLCBvbGRTaXplKTsKCQkJCX0KCQkJCS8vIGFkZCBsaXN0ZW5lciB0byBsYXN0IHBvc2l0aW9uCgkJCQluZXdMaXN0ZW5lcnNbbmV3U2l6ZSAtIDFdID0gbGlzdGVuZXI7CgkJCQkvLwoJCQkJLy8gbm93IHN3aXRjaCBuZXcgZm9yIG9sZAoJCQkJZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQkvLwoJCQl9CgkJfQoJfQoKCS8qKgoJICogVGhlIFN0cnVjdHVyZWREb2N1bWVudExpc3RuZXJzIGFuZCBNb2RlbENoYWduZWRMaXN0ZW5lcnMgYXJlIHZlcnkKCSAqIHNpbWlsYXIuIFRoZXkgYm90aCByZWNlaXZlIGlkZW50aWNhbCBldmVudHMuIFRoZSBkaWZmZXJlbmNlIGlzIHRoZQoJICogdGltaW5nLiBUaGUgInB1cmUiIFN0cnVjdHVyZWREb2N1bWVudExpc3RuZXJzIGFyZSBub3RpZmllZCBhZnRlciB0aGUKCSAqIHN0cnVjdHVyZWREb2N1bWVudCBoYXMgYmVlbiBjaGFuZ2VkLCBidXQgYmVmb3JlIG90aGVyLCByZWxhdGVkIG1vZGVscwoJICogbWF5IGhhdmUgYmVlbiBjaGFuZ2VkIHN1Y2ggYXMgdGhlIFN0cnVjdHVyYWwgTW9kZWwuIFRoZSBTdHJ1Y3R1cmFsCgkgKiBtb2RlbCBpcyBpbiBmYWN0IGl0c2VsZiBhICJwdXJlIiBTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0bmVyLiBUaGUKCSAqIE1vZGVsQ2hhbmdlZExpc3RlbmVycyBjYW4gcmVzdCBhc3N1cmVkIHRoYXQgYWxsIG1vZGVscyBhbmQgZGF0YSBoYXZlCgkgKiBiZWVuIHVwZGF0ZWQgZnJvbSB0aGUgY2hhbmdlIGJ5IHRoZSB0aWVtIHRoZXkgYXJlIG5vdGlmaWVkLiBUaGlzIGlzCgkgKiBlc3BlY2lhbGx5IGltcG9ydGFudCBmb3IgdGhlIHRleHQgd2lkZ2V0LCBmb3IgZXhhbXBsZSwgd2hpY2ggbWF5IHJlbHkKCSAqIG9uIGJvdGggc3RydWN0dXJlZERvY3VtZW50IGFuZCBzdHJ1Y3R1cmFsIG1vZGVsIGluZm9ybWF0aW9uLgoJICovCglwdWJsaWMgdm9pZCBhZGREb2N1bWVudENoYW5nZWRMaXN0ZW5lcihJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKERlYnVnLmRlYnVnU3RydWN0dXJlZERvY3VtZW50KSB7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZE1vZGVsQ2hhbmdlZExpc3RlbmVyLiBSZXF1ZXN0IHRvIGFkZCBhbiBpbnN0YW5jZSBvZiAiICsgbGlzdGVuZXIuZ2V0Q2xhc3MoKSArICIgYXMgYSBsaXN0ZW5lciBvbiBzdHJ1Y3R1cmVkRG9jdW1lbnQuIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCX0KCQkJLy8gbWFrZSBzdXJlIGxpc3RlbmVyIGlzIG5vdCBhbHJlYWR5IGluIGxpc3RlbmluZwoJCQkvLyAoYW5kIGlmIGl0IGlzLCBwcmludCBhIHdhcm5pbmcgdG8gYWlkIGRlYnVnZ2luZywgaWYgbmVlZGVkKQoJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCWlmIChEZWJ1Zy5kaXNwbGF5V2FybmluZ3MpIHsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZE1vZGVsQ2hhbmdlZExpc3RlbmVyLiBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIHdhcyBhZGRlZGVkIG1vcmUgdGhhbiBvbmNlLiAiKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCQllbHNlIHsKCQkJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkTW9kZWxDaGFuZ2VkTGlzdGVuZXIuIEFkZGluZyBhbiBpbnN0YW5jZSBvZiAiICsgbGlzdGVuZXIuZ2V0Q2xhc3MoKSArICIgYXMgYSBsaXN0ZW5lciBvbiBzdHJ1Y3R1cmVkRG9jdW1lbnQuIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCQlpbnQgb2xkU2l6ZSA9IDA7CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCS8vIG5vcm1hbGx5IHdvbid0IGJlIG51bGwsIGJ1dCB3ZSBuZWVkIHRvIGJlIHN1cmUsIGZvcgoJCQkJCS8vIGZpcnN0CgkJCQkJLy8gdGltZSB0aHJvdWdoCgkJCQkJb2xkU2l6ZSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLmxlbmd0aDsKCQkJCX0KCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSArIDE7CgkJCQlPYmplY3RbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgT2JqZWN0W25ld1NpemVdOwoJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQlTeXN0ZW0uYXJyYXljb3B5KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCAwLCBuZXdMaXN0ZW5lcnMsIDAsIG9sZFNpemUpOwoJCQkJfQoJCQkJLy8gYWRkIGxpc3RlbmVyIHRvIGxhc3QgcG9zaXRpb24KCQkJCW5ld0xpc3RlbmVyc1tuZXdTaXplIC0gMV0gPSBsaXN0ZW5lcjsKCQkJCS8vCgkJCQkvLyBub3cgc3dpdGNoIG5ldyBmb3Igb2xkCgkJCQlmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJCS8vCgkJCQkvLyB3aGVuIGEgbGlzdGVuZXIgaXMgYWRkZWQsCgkJCQkvLyBzZW5kIHRoZSBuZXcgbW9kZWwgZXZlbnQgdG8gdGhhdCBvbmUgcGFydGljdWxhciBsaXN0ZW5lciwKCQkJCS8vIHNvIGl0CgkJCQkvLyBjYW4gaW5pdGlhbGl6ZSBpdHNlbGYgd2l0aCB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgbW9kZWwKCQkJCS8vIGxpc3RlbmVyLm5ld01vZGVsKG5ldyBOZXdNb2RlbEV2ZW50KHRoaXMsIGxpc3RlbmVyKSk7CgkJCX0KCQl9Cgl9CgoJcHVibGljIHZvaWQgYWRkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVyKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpIHsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIuIFJlcXVlc3QgdG8gYWRkIGFuIGluc3RhbmNlIG9mICIgKyBsaXN0ZW5lci5nZXRDbGFzcygpICsgIiBhcyBhIGxpc3RlbmVyIG9uIHN0cnVjdHVyZWREb2N1bWVudC4iKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJfQoJCQkvLyBtYWtlIHN1cmUgbGlzdGVuZXIgaXMgbm90IGFscmVhZHkgaW4gbGlzdGVuaW5nCgkJCS8vIChhbmQgaWYgaXQgaXMsIHByaW50IGEgd2FybmluZyB0byBhaWQgZGVidWdnaW5nLCBpZiBuZWVkZWQpCgkJCWlmIChVdGlsaXRpZXMuY29udGFpbnMoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCWlmIChEZWJ1Zy5kaXNwbGF5V2FybmluZ3MpIHsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZFN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyLiBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIHdhcyBhZGRlZGVkIG1vcmUgdGhhbiBvbmNlLiAiKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCQllbHNlIHsKCQkJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIuIEFkZGluZyBhbiBpbnN0YW5jZSBvZiAiICsgbGlzdGVuZXIuZ2V0Q2xhc3MoKSArICIgYXMgYSBsaXN0ZW5lciBvbiBzdHJ1Y3R1cmVkRG9jdW1lbnQuIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCQlpbnQgb2xkU2l6ZSA9IDA7CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQkvLyBub3JtYWxseSB3b24ndCBiZSBudWxsLCBidXQgd2UgbmVlZCB0byBiZSBzdXJlLCBmb3IKCQkJCQkvLyBmaXJzdAoJCQkJCS8vIHRpbWUgdGhyb3VnaAoJCQkJCW9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJfQoJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplICsgMTsKCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQlTeXN0ZW0uYXJyYXljb3B5KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgMCwgbmV3TGlzdGVuZXJzLCAwLCBvbGRTaXplKTsKCQkJCX0KCQkJCS8vIGFkZCBsaXN0ZW5lciB0byBsYXN0IHBvc2l0aW9uCgkJCQluZXdMaXN0ZW5lcnNbbmV3U2l6ZSAtIDFdID0gbGlzdGVuZXI7CgkJCQkvLwoJCQkJLy8gbm93IHN3aXRjaCBuZXcgZm9yIG9sZAoJCQkJZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJLy8KCQkJCS8vIHdoZW4gYSBsaXN0ZW5lciBpcyBhZGRlZCwKCQkJCS8vIHNlbmQgdGhlIG5ldyBtb2RlbCBldmVudCB0byB0aGF0IG9uZSBwYXJ0aWN1bGFyIGxpc3RlbmVyLAoJCQkJLy8gc28gaXQKCQkJCS8vIGNhbiBpbml0aWFsaXplIGl0c2VsZiB3aXRoIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBtb2RlbAoJCQkJLy8gbGlzdGVuZXIubmV3TW9kZWwobmV3IE5ld01vZGVsRXZlbnQodGhpcywgbGlzdGVuZXIpKTsKCQkJfQoJCX0KCX0KCgkvKioKCSAqIFdlIG1hbmFnZSBvdXIgb3duIGRvY3VtZW50IGxpc3RuZXJzLCBpbnN0ZWFkIG9mIGRlbGVnYXRpbmcgdG8gb3VyCgkgKiBwYXJlbnREb2N1bWVudCwgc28gd2UgY2FuIGZpcmUgYXQgdmVyeSBlbmQgKGFuZCBub3Qgd2hlbiB0aGUKCSAqIHBhcmVudERvY3VtZW50IGNoYW5nZXMpLgoJICogCgkgKi8KCXB1YmxpYyB2b2lkIGFkZERvY3VtZW50TGlzdGVuZXIoSURvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJLy8gbWFrZSBzdXJlIGxpc3RlbmVyIGlzIG5vdCBhbHJlYWR5IGluIGxpc3RlbmluZwoJCQkvLyAoYW5kIGlmIGl0IGlzLCBwcmludCBhIHdhcm5pbmcgdG8gYWlkIGRlYnVnZ2luZywgaWYgbmVlZGVkKQoJCQlpZiAoIVV0aWxpdGllcy5jb250YWlucyhmRG9jdW1lbnRMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJaW50IG9sZFNpemUgPSAwOwoJCQkJaWYgKGZEb2N1bWVudExpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJLy8gbm9ybWFsbHkgd29uJ3QgYmUgbnVsbCwgYnV0IHdlIG5lZWQgdG8gYmUgc3VyZSwgZm9yCgkJCQkJLy8gZmlyc3QKCQkJCQkvLyB0aW1lIHRocm91Z2gKCQkJCQlvbGRTaXplID0gZkRvY3VtZW50TGlzdGVuZXJzLmxlbmd0aDsKCQkJCX0KCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSArIDE7CgkJCQlJRG9jdW1lbnRMaXN0ZW5lcltdIG5ld0xpc3RlbmVycyA9IG51bGw7CgkJCQluZXdMaXN0ZW5lcnMgPSBuZXcgSURvY3VtZW50TGlzdGVuZXJbbmV3U2l6ZV07CgkJCQlpZiAoZkRvY3VtZW50TGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQlTeXN0ZW0uYXJyYXljb3B5KGZEb2N1bWVudExpc3RlbmVycywgMCwgbmV3TGlzdGVuZXJzLCAwLCBvbGRTaXplKTsKCQkJCX0KCQkJCS8vIGFkZCBsaXN0ZW5lciB0byBsYXN0IHBvc2l0aW9uCgkJCQluZXdMaXN0ZW5lcnNbbmV3U2l6ZSAtIDFdID0gbGlzdGVuZXI7CgkJCQkvLyBub3cgc3dpdGNoIG5ldyBmb3Igb2xkCgkJCQlmRG9jdW1lbnRMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCX0KCQl9Cgl9CgoJLyoKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnQjYWRkRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcihvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKQoJICogCgkgKiBSZWdpc3RlcnMgdGhlIGRvY3VtZW50IHBhcnRpdGlvbmluZyBsaXN0ZW5lciB3aXRoIHRoZSBkb2N1bWVudC4gQWZ0ZXIKCSAqIHJlZ2lzdHJhdGlvbiB0aGUgSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIgaXMgaW5mb3JtZWQgYWJvdXQgZWFjaAoJICogcGFydGl0aW9uIGNoYW5nZSBjYXVzZSBieSBhIGRvY3VtZW50IG1hbmlwdWxhdGlvbi4gSWYgYSBkb2N1bWVudAoJICogcGFydGl0aW9uaW5nIGxpc3RlbmVyIGlzIGFsc28gYSBkb2N1bWVudCBsaXN0ZW5lciwgdGhlIGZvbGxvd2luZwoJICogbm90aWZpY2F0aW9uIHNlcXVlbmNlIGlzIGd1YXJhbnRlZWQgaWYgYSBkb2N1bWVudCBtYW5pcHVsYXRpb24gY2hhbmdlcwoJICogdGhlIGRvY3VtZW50IHBhcnRpdGlvbmluZzogMSkKCSAqIGxpc3RlbmVyLmRvY3VtZW50QWJvdXRUb0JlQ2hhbmdlZChEb2N1bWVudEV2ZW50KTsgMikKCSAqIGxpc3RlbmVyLmRvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZCgpOyAzKQoJICogbGlzdGVuZXIuZG9jdW1lbnRDaGFuZ2VkKERvY3VtZW50RXZlbnQpOyBJZiB0aGUgbGlzdGVuZXIgaXMgYWxyZWFkeQoJICogcmVnaXN0ZXJlZCBub3RoaW5nIGhhcHBlbnMuCgkgKiAKCSAqIEBzZWUgSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIKCSAqLwoKCXB1YmxpYyB2b2lkIGFkZERvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIoSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJQXNzZXJ0LmlzTm90TnVsbChsaXN0ZW5lcik7CgkJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMgPT0gbnVsbCkgewoJCQkJZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzID0gbmV3IEFycmF5TGlzdCgxKTsKCQkJfQoJCQlpZiAoIWZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycy5jb250YWlucyhsaXN0ZW5lcikpCgkJCQlmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTsKCQl9Cgl9CgoJLyoqCgkgKiBBZGRzIHRoZSBwb3NpdGlvbiB0byB0aGUgZG9jdW1lbnQncyBkZWZhdWx0IHBvc2l0aW9uIGNhdGVnb3J5LiBUaGUKCSAqIGRlZmF1bHQgY2F0ZWdvcnkgbXVzdCBiZSBzcGVjaWZpZWQgYnkgdGhlIGltcGxlbWVudGVyLiBBIHBvc2l0aW9uIHRoYXQKCSAqIGhhcyBiZWVuIGFkZGVkIHRvIGEgcG9zaXRpb24gY2F0ZWdvcnkgaXMgdXBkYXRlZCBhdCBlYWNoIGNoYW5nZSBhcHBsaWVkCgkgKiB0byB0aGUgZG9jdW1lbnQuCgkgKiAKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHBvc2l0aW9uIGlzIG5vdCBhIHZhbGlkIHJhbmdlIGluIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgdm9pZCBhZGRQb3NpdGlvbihQb3NpdGlvbiBwb3NpdGlvbikgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5hZGRQb3NpdGlvbihwb3NpdGlvbik7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNhZGRQb3NpdGlvbgoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgcG9zaXRpb24gaXMgbm90IGEgdmFsaWQgcmFuZ2UgaW4gdGhlIGRvY3VtZW50CgkgKiBAZXhjZXB0aW9uIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHRoZSBjYXRlZ29yeSBpcyBub3QgZGVmaW5lZCBmb3IgdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyB2b2lkIGFkZFBvc2l0aW9uKFN0cmluZyBjYXRlZ29yeSwgUG9zaXRpb24gcG9zaXRpb24pIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiwgQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkuYWRkUG9zaXRpb24oY2F0ZWdvcnksIHBvc2l0aW9uKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2FkZFBvc2l0aW9uQ2F0ZWdvcnkKCSAqLwoJcHVibGljIHZvaWQgYWRkUG9zaXRpb25DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnkpIHsKCQlpbnRlcm5hbF9hZGRQb3NpdGlvbkNhdGVnb3J5KGNhdGVnb3J5KTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2FkZFBvc2l0aW9uVXBkYXRlcgoJICovCglwdWJsaWMgdm9pZCBhZGRQb3NpdGlvblVwZGF0ZXIoSVBvc2l0aW9uVXBkYXRlciB1cGRhdGVyKSB7CgkJaW50ZXJuYWxfYWRkUG9zaXRpb25VcGRhdGVyKHVwZGF0ZXIpOwoJfQoKCS8qKgoJICogQWRkcyB0aGUgZ2l2ZW4gZG9jdW1lbnQgbGlzdGVuZXIgYXMgb25lIHdoaWNoIGlzIG5vdGlmaWVkIGJlZm9yZSB0aG9zZQoJICogZG9jdW1lbnQgbGlzdGVuZXJzIGFkZGVkIHdpdGggPGNvZGU+YWRkRG9jdW1lbnRMaXN0ZW5lcjwvY29kZT4gYXJlCgkgKiBub3RpZmllZC4gSWYgdGhlIGdpdmVuIGxpc3RlbmVyIGlzIGFsc28gcmVnaXN0ZXJlZCB1c2luZwoJICogPGNvZGU+YWRkRG9jdW1lbnRMaXN0ZW5lcjwvY29kZT4gaXQgd2lsbCBiZSBub3RpZmllZCB0d2ljZS4gSWYgdGhlCgkgKiBsaXN0ZW5lciBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgbm90aGluZyBoYXBwZW5zLgoJICogPHA+CgkgKiAKCSAqIFRoaXMgbWV0aG9kIGlzIG5vdCBmb3IgcHVibGljIHVzZSwgaXQgbWF5IG9ubHkgYmUgY2FsbGVkIGJ5CgkgKiBpbXBsZW1lbnRlcnMgb2YgPGNvZGU+SURvY3VtZW50QWRhcHRlcjwvY29kZT4gYW5kIG9ubHkgaWYgdGhvc2UKCSAqIGltcGxlbWVudGVycyBuZWVkIHRvIGltcGxlbWVudCA8Y29kZT5JRG9jdW1lbnRMaXN0ZW5lcjwvY29kZT4uCgkgKiAKCSAqIEBwYXJhbSBkb2N1bWVudEFkYXB0ZXIKCSAqICAgICAgICAgICAgdGhlIGxpc3RlbmVyIHRvIGJlIGFkZGVkIGFzIHByZW5vdGlmaWVkIGRvY3VtZW50IGxpc3RlbmVyCgkgKi8KCXB1YmxpYyB2b2lkIGFkZFByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcihJRG9jdW1lbnRMaXN0ZW5lciBkb2N1bWVudEFkYXB0ZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCWludCBwcmV2aW91c1NpemUgPSBmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycy5sZW5ndGg7CgkJCQlJRG9jdW1lbnRMaXN0ZW5lcltdIGxpc3RlbmVycyA9IG5ldyBJRG9jdW1lbnRMaXN0ZW5lcltwcmV2aW91c1NpemUgKyAxXTsKCQkJCVN5c3RlbS5hcnJheWNvcHkoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIDAsIGxpc3RlbmVycywgMCwgcHJldmlvdXNTaXplKTsKCQkJCWxpc3RlbmVyc1twcmV2aW91c1NpemVdID0gZG9jdW1lbnRBZGFwdGVyOwoJCQkJZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCX0KCQkJZWxzZSB7CgkJCQlmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycyA9IG5ldyBJRG9jdW1lbnRMaXN0ZW5lclsxXTsKCQkJCWZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzWzBdID0gZG9jdW1lbnRBZGFwdGVyOwoJCQl9CgkJfQoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgamF2YS5sYW5nLkNoYXJTZXF1ZW5jZSNjaGFyQXQoaW50KQoJICovCglwdWJsaWMgY2hhciBjaGFyQXQoaW50IGFyZzApIHsKCQl0cnkgewoJCQlyZXR1cm4gZ2V0Q2hhcigwKTsKCQl9CgkJY2F0Y2ggKEJhZExvY2F0aW9uRXhjZXB0aW9uIGUpIHsKCQkJdGhyb3cgbmV3IEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24oKTsKCQl9Cgl9CgoJLyoqCgkgKiBUaGlzIGZvcm0gb2YgdGhlIEFQSSByZW1vdmVzIGFsbCByZWFkIG9ubHkgcG9zaXRpb25zLCBhcyBzaG91bGQgYmUgZG9uZQoJICogd2UgJ3NldFRleHQnIGlzIGNhbGxlZC4gTm90ZTogYW4gYWx0ZXJuYXRpdmUgYWxnb3JpdGhtIG1heSBzaW1wbHkKCSAqIHJlbW92ZSB0aGUgY2F0ZWdvcnkgKGFuZCBpdCB3b3VsZCBnZXQgYWRkZWQgYmFjayBpbiBsYXRlciwgaWYvd2hlbgoJICogcmVhZG9ubHkgcmVnaW9ucyBhZGRlZC4KCSAqLwoJcHJpdmF0ZSB2b2lkIGNsZWFyUmVhZE9ubHkoKSB7CgkJUG9zaXRpb25bXSBwb3NpdGlvbnMgPSBudWxsOwoJCXRyeSB7CgkJCXBvc2l0aW9ucyA9IGdldFBvc2l0aW9ucyhSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSk7CgkJfQoJCWNhdGNoIChCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIGUpIHsKCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbigicHJvZ3JhbSBlcnJvcjogc2hvdWxkIG5ldmVyIG9jY3VyIiwgZSk7IC8vJE5PTi1OTFMtMSQKCQl9CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspIHsKCQkJUG9zaXRpb24gcG9zaXRpb24gPSBwb3NpdGlvbnNbaV07CgkJCS8vIG5vdGUgd2UgZG9uJ3QgZmlyZSB0aGUgImFib3V0IHRvIGNoYW5nZSIgb3IgImNoYW5nZWQiIGV2ZW50cywKCQkJLy8gc2luY2UgcHJlc3VtYWJseSwgdGV4dCBpcyBhbGwgZ29pbmcgYXdheSBhbmQgYmVpbmcgcmVwbGFjZWQKCQkJLy8gYW55d2F5LgoJCQlwb3NpdGlvbi5kZWxldGUoKTsKCQl9Cgl9CgoKCXB1YmxpYyB2b2lkIGNsZWFyUmVhZE9ubHkoaW50IHN0YXJ0T2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJLy8gVE9ETyBEVyBJIHN0aWxsIG5lZWQgdG8gaW1wbGVtZW50IHNtYXJ0ZXIgYWxnb3JpdGhtIHRoYXQKCQkvLyBhZHVzdCBleGlzdGluZyBSTyByZWdpb25zLCBpZiBuZWVkZWQuIEZvciBub3csIEknbGwganVzdAoJCS8vIHJlbW92ZSBhbnkgdGhhdCBvdmVybGFwLgoJCXRyeSB7CgkJCVBvc2l0aW9uW10gcG9zaXRpb25zID0gZ2V0UG9zaXRpb25zKFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZKTsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspIHsKCQkJCVBvc2l0aW9uIHBvc2l0aW9uID0gcG9zaXRpb25zW2ldOwoJCQkJaWYgKHBvc2l0aW9uLm92ZXJsYXBzV2l0aChzdGFydE9mZnNldCwgbGVuZ3RoKSkgewoJCQkJCVN0cmluZyBlZmZlY3RlZFRleHQgPSB0aGlzLmdldChzdGFydE9mZnNldCwgbGVuZ3RoKTsKCQkJCQkvLyBmRG9jdW1lbnRFdmVudCA9IG5ldyBEb2N1bWVudEV2ZW50KHRoaXMsIHN0YXJ0T2Zmc2V0LAoJCQkJCS8vIGxlbmd0aCwgZWZmZWN0ZWRUZXh0KTsKCQkJCQlmaXJlUmVhZE9ubHlBYm91dFRvQmVDaGFuZ2VkKCk7CgkJCQkJcG9zaXRpb24uZGVsZXRlKCk7CgkJCQkJTm9DaGFuZ2VFdmVudCBub0NoYW5nZUV2ZW50ID0gbmV3IE5vQ2hhbmdlRXZlbnQodGhpcywgbnVsbCwgZWZmZWN0ZWRUZXh0LCBzdGFydE9mZnNldCwgbGVuZ3RoKTsKCQkJCQlub0NoYW5nZUV2ZW50LnJlYXNvbiA9IE5vQ2hhbmdlRXZlbnQuUkVBRF9PTkxZX1NUQVRFX0NIQU5HRTsKCQkJCQlmaXJlUmVhZE9ubHlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChub0NoYW5nZUV2ZW50KTsKCQkJCX0KCQkJfQoJCX0KCQljYXRjaCAoQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiBlKSB7CgkJCS8vIGp1c3QgbWVhbnMgbm8gcmVhZG9ubHkgcmVnaW9ucyBiZWVuIGRlZmluZWQgeWV0CgkJCS8vIHNvIG5vdGhpbmcgdG8gZG8uCgkJfQoJfQoKCS8qKgoJICogQ29tcHV0ZXMgdGhlIGluZGV4IGF0IHdoaWNoIGEgPGNvZGU+UG9zaXRpb248L2NvZGU+IHdpdGggdGhlCgkgKiBzcGVjaWZpZWQgb2Zmc2V0IHdvdWxkIGJlIGluc2VydGVkIGludG8gdGhlIGdpdmVuIGNhdGVnb3J5LiBBcyB0aGUKCSAqIG9yZGVyaW5nIGluc2lkZSBhIGNhdGVnb3J5IG9ubHkgZGVwZW5kcyBvbiB0aGUgb2Zmc2V0LCB0aGUgaW5kZXggbXVzdAoJICogYmUgY2hvb3NlbiB0byBiZSB0aGUgZmlyc3Qgb2YgYWxsIHBvc2l0aW9ucyB3aXRoIHRoZSBzYW1lIG9mZnNldC4KCSAqIAoJICogQHBhcmFtIGNhdGVnb3J5CgkgKiAgICAgICAgICAgIHRoZSBjYXRlZ29yeSBpbiB3aGljaCB3b3VsZCBiZSBhZGRlZAoJICogQHBhcmFtIG9mZnNldAoJICogICAgICAgICAgICB0aGUgcG9zaXRpb24gb2Zmc2V0IHRvIGJlIGNvbnNpZGVyZWQKCSAqIEByZXR1cm4gdGhlIGluZGV4IGludG8gdGhlIGNhdGVnb3J5CgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBpZiBvZmZzZXQgaXMgaW52YWxpZCBpbiB0aGlzIGRvY3VtZW50CgkgKiBAZXhjZXB0aW9uIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIGNhdGVnb3J5IGlzIHVuZGVmaW5lZCBpbiB0aGlzIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBpbnQgY29tcHV0ZUluZGV4SW5DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnksIGludCBvZmZzZXQpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24sIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5jb21wdXRlSW5kZXhJbkNhdGVnb3J5KGNhdGVnb3J5LCBvZmZzZXQpOwoJfQoKCS8qKgoJICogQ29tcHV0ZXMgdGhlIG51bWJlciBvZiBsaW5lcyBpbiB0aGUgZ2l2ZW4gdGV4dC4gRm9yIGEgZ2l2ZW4gaW1wbGVtZW50ZXIKCSAqIG9mIHRoaXMgaW50ZXJmYWNlIHRoaXMgbWV0aG9kIHJldHVybnMgdGhlIHNhbWUgcmVzdWx0IGFzCgkgKiA8Y29kZT5zZXQodGV4dCk7IGdldE51bWJlck9mTGluZXMoKTwvY29kZT4uCgkgKiAKCSAqIEBwYXJhbSB0ZXh0CgkgKiAgICAgICAgICAgIHRoZSB0ZXh0IHdob3NlIG51bWJlciBvZiBsaW5lcyBzaG91bGQgYmUgY29tcHV0ZWQKCSAqIEByZXR1cm4gdGhlIG51bWJlciBvZiBsaW5lcyBpbiB0aGUgZ2l2ZW4gdGV4dAoJICovCglwdWJsaWMgaW50IGNvbXB1dGVOdW1iZXJPZkxpbmVzKFN0cmluZyB0ZXh0KSB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5jb21wdXRlTnVtYmVyT2ZMaW5lcyh0ZXh0KTsKCX0KCgkvKioKCSAqIENvbXB1dGVzIHRoZSBwYXJ0aXRpb25pbmcgb2YgdGhlIGdpdmVuIGRvY3VtZW50IHJhbmdlIHVzaW5nIHRoZQoJICogZG9jdW1lbnQncyBwYXJ0aXRpb25lci4KCSAqIAoJICogQHBhcmFtIG9mZnNldAoJICogICAgICAgICAgICB0aGUgZG9jdW1lbnQgb2Zmc2V0IGF0IHdoaWNoIHRoZSByYW5nZSBzdGFydHMKCSAqIEBwYXJhbSBsZW5ndGgKCSAqICAgICAgICAgICAgdGhlIGxlbmd0aCBvZiB0aGUgZG9jdW1lbnQgcmFuZ2UKCSAqIEByZXR1cm4gYSBzcGVjaWZpY2F0aW9uIG9mIHRoZSByYW5nZSdzIHBhcnRpdGlvbmluZwoJICogQHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogQHRocm93cyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24KCSAqLwoJcHVibGljIElUeXBlZFJlZ2lvbltdIGNvbXB1dGVQYXJ0aXRpb25pbmcoaW50IG9mZnNldCwgaW50IGxlbmd0aCkgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlJVHlwZWRSZWdpb25bXSB0eXBlZFJlZ2lvbnMgPSBudWxsOwoJCXRyeSB7CgkJCXR5cGVkUmVnaW9ucyA9IGNvbXB1dGVQYXJ0aXRpb25pbmcoSVN0cnVjdHVyZWRQYXJ0aXRpb25pbmcuREVGQVVMVF9TVFJVQ1RVUkVEX1BBUlRJVElPTklORywgb2Zmc2V0LCBsZW5ndGgsIGZhbHNlKTsKCQl9CgkJY2F0Y2ggKEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiBlKSB7CgkJCS8vIGltcG9zc2libGUgaW4gdGhpcyBjb250ZXh0CgkJCXRocm93IG5ldyBFcnJvcihlKTsKCQl9CgkJaWYgKHR5cGVkUmVnaW9ucyA9PSBudWxsKSB7CgkJCXR5cGVkUmVnaW9ucyA9IG5ldyBJVHlwZWRSZWdpb25bMF07CgkJfQoJCXJldHVybiB0eXBlZFJlZ2lvbnM7Cgl9CgoKCXB1YmxpYyBJVHlwZWRSZWdpb25bXSBjb21wdXRlUGFydGl0aW9uaW5nKFN0cmluZyBwYXJ0aXRpb25pbmcsIGludCBvZmZzZXQsIGludCBsZW5ndGgsIGJvb2xlYW4gaW5jbHVkZVplcm9MZW5ndGhQYXJ0aXRpb25zKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24sIEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiB7CgkJaWYgKCgwID4gb2Zmc2V0KSB8fCAoMCA+IGxlbmd0aCkgfHwgKG9mZnNldCArIGxlbmd0aCA+IGdldExlbmd0aCgpKSkKCQkJdGhyb3cgbmV3IEJhZExvY2F0aW9uRXhjZXB0aW9uKCk7CgoJCUlEb2N1bWVudFBhcnRpdGlvbmVyIHBhcnRpdGlvbmVyID0gZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcihwYXJ0aXRpb25pbmcpOwoKCQlpZiAocGFydGl0aW9uZXIgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjIpCgkJCXJldHVybiAoKElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMikgcGFydGl0aW9uZXIpLmNvbXB1dGVQYXJ0aXRpb25pbmcob2Zmc2V0LCBsZW5ndGgsIGluY2x1ZGVaZXJvTGVuZ3RoUGFydGl0aW9ucyk7CgkJZWxzZSBpZiAocGFydGl0aW9uZXIgIT0gbnVsbCkKCQkJcmV0dXJuIHBhcnRpdGlvbmVyLmNvbXB1dGVQYXJ0aXRpb25pbmcob2Zmc2V0LCBsZW5ndGgpOwoJCWVsc2UgaWYgKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcuZXF1YWxzKHBhcnRpdGlvbmluZykpCgkJCXJldHVybiBuZXcgVHlwZWRSZWdpb25bXXtuZXcgVHlwZWRSZWdpb24ob2Zmc2V0LCBsZW5ndGgsIERFRkFVTFRfQ09OVEVOVF9UWVBFKX07CgkJZWxzZQoJCQl0aHJvdyBuZXcgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uKCk7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNjb250YWluc1Bvc2l0aW9uCgkgKi8KCXB1YmxpYyBib29sZWFuIGNvbnRhaW5zUG9zaXRpb24oU3RyaW5nIGNhdGVnb3J5LCBpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJcmV0dXJuIGdldFBvc2l0aW9uTWFuYWdlcigpLmNvbnRhaW5zUG9zaXRpb24oY2F0ZWdvcnksIG9mZnNldCwgbGVuZ3RoKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2NvbnRhaW5zUG9zaXRpb25DYXRlZ29yeQoJICovCglwdWJsaWMgYm9vbGVhbiBjb250YWluc1Bvc2l0aW9uQ2F0ZWdvcnkoU3RyaW5nIGNhdGVnb3J5KSB7CgkJcmV0dXJuIGdldFBvc2l0aW9uTWFuYWdlcigpLmNvbnRhaW5zUG9zaXRpb25DYXRlZ29yeShjYXRlZ29yeSk7Cgl9CgoJcHVibGljIGJvb2xlYW4gY29udGFpbnNSZWFkT25seShpbnQgc3RhcnRPZmZzZXQsIGludCBsZW5ndGgpIHsKCQlib29sZWFuIHJlc3VsdCA9IGZhbHNlOwoJCXRyeSB7CgkJCVBvc2l0aW9uW10gcG9zaXRpb25zID0gZ2V0UG9zaXRpb25zKFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZKTsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspIHsKCQkJCVBvc2l0aW9uIHBvc2l0aW9uID0gcG9zaXRpb25zW2ldOwoJCQkJaWYgKHBvc2l0aW9uLm92ZXJsYXBzV2l0aChzdGFydE9mZnNldCwgbGVuZ3RoKSkgewoJCQkJCXJlc3VsdCA9IHRydWU7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCX0KCQl9CgkJY2F0Y2ggKEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gZSkgewoJCQkvLyBqdXN0IG1lYW5zIG5vIHJlYWRvbmx5IHJlZ2lvbnMgYmVlbiBkZWZpbmVkIHlldAoJCQkvLyBzbyBvYnZpb3VzbHkgZmFsc2UKCQkJcmVzdWx0ID0gZmFsc2U7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJcHJpdmF0ZSB2b2lkIGV4ZWN1dGVQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlcygpIHsKCQlpZiAoZlN0b3BwZWRDb3VudCA+IDApCgkJCXJldHVybjsKCQl3aGlsZSAoZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzICE9IG51bGwpIHsKCQkJTGlzdCBjaGFuZ2VzID0gZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzOwoJCQlmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMgPSBudWxsOwoJCQlJdGVyYXRvciBlID0gY2hhbmdlcy5pdGVyYXRvcigpOwoJCQl3aGlsZSAoZS5oYXNOZXh0KCkpIHsKCQkJCVJlZ2lzdGVyZWRSZXBsYWNlIHJlcGxhY2UgPSAoUmVnaXN0ZXJlZFJlcGxhY2UpIGUubmV4dCgpOwoJCQkJcmVwbGFjZS5mUmVwbGFjZS5wZXJmb3JtKHRoaXMsIHJlcGxhY2UuZk93bmVyKTsKCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZWQoKSB7CgkJLy8gbW9zdCBEb2N1bWVudEFib3V0VG9CZUNoYW5nZWQgbGlzdGVuZXJzIGRvIG5vdCBhbnRpY2lwYXRlCgkJLy8gRG9jdW1lbnRFdmVudCA9PSBudWxsLiBTbyBtYWtlIHN1cmUgZG9jdW1lbnRFdmVudCBpcyBub3QKCQkvLyBudWxsLiAodGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLCB5ZXQgaXQgZG9lcyBzb21ldGltZXMpCgkJaWYgKGZEb2N1bWVudEV2ZW50ID09IG51bGwpIHsKCQkJZkRvY3VtZW50RXZlbnQgPSBuZXcgTnVsbERvY3VtZW50RXZlbnQoKTsKCQl9CgoJCV9maXJlU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZShmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyk7CgkJLy8gTm90ZTogdGhlIGRvY0V2ZW50IGlzIGNyZWF0ZWQgaW4gcmVwbGFjZVRleHQgQVBJISAob3Igc2V0IFRleHQpCgkJX2ZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2UoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMpOwoJCW5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzQWJvdXRUb0NoYW5nZShmRG9jdW1lbnRFdmVudCk7CgkJX2ZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2UoZkRvY3VtZW50TGlzdGVuZXJzKTsKCX0KCgkvKioKCSAqIEZpcmVzIHRoZSBkb2N1bWVudCBwYXJ0aXRpb25pbmcgY2hhbmdlZCBub3RpZmljYXRpb24gdG8gYWxsIHJlZ2lzdGVyZWQKCSAqIGRvY3VtZW50IHBhcnRpdGlvbmluZyBsaXN0ZW5lcnMuIFVzZXMgYSByb2J1c3QgaXRlcmF0b3IuCgkgKiAKCSAqIEBwYXJhbSBldmVudAoJICogICAgICAgICAgICB0aGUgZG9jdW1lbnQgcGFydGl0aW9uaW5nIGNoYW5nZWQgZXZlbnQKCSAqIAoJICogQHNlZSBJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbjIKCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmlyZURvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZChEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWRFdmVudCBldmVudCkgewoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMgPT0gbnVsbCB8fCBmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMuc2l6ZSgpID09IDApCgkJCXJldHVybjsKCgkJTGlzdCBsaXN0ID0gbmV3IEFycmF5TGlzdChmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMpOwoJCUl0ZXJhdG9yIGUgPSBsaXN0Lml0ZXJhdG9yKCk7CgkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCUlEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyIGwgPSAoSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIpIGUubmV4dCgpOwoJCQlpZiAobCBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uMikgewoJCQkJSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24yIGV4dGVuc2lvbjIgPSAoSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24yKSBsOwoJCQkJZXh0ZW5zaW9uMi5kb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWQoZXZlbnQpOwoJCQl9CgkJCWVsc2UgaWYgKGwgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbikgewoJCQkJSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24gZXh0ZW5zaW9uID0gKElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uKSBsOwoJCQkJZXh0ZW5zaW9uLmRvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZCh0aGlzLCBldmVudC5nZXRDb3ZlcmFnZSgpKTsKCQkJfQoJCQllbHNlIHsKCQkJCWwuZG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkKHRoaXMpOwoJCQl9CgkJfQoKCX0KCglwcml2YXRlIHZvaWQgZmlyZVJlYWRPbmx5QWJvdXRUb0JlQ2hhbmdlZCgpIHsKCQlfZmlyZVN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2UoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMpOwoJCS8vIE5vdGU6IHRoZSBkb2NFdmVudCBpcyBjcmVhdGVkIGluIHJlcGxhY2VUZXh0IEFQSSEgKG9yIHNldCBUZXh0KQoJCS8vIF9maXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzKTsKCQkvLyBfZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZShmRG9jdW1lbnRMaXN0ZW5lcnMpOwoJfQoKCXByaXZhdGUgdm9pZCBmaXJlUmVhZE9ubHlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChOb0NoYW5nZUV2ZW50IGV2ZW50KSB7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBldmVudCk7CgkJLy8gX2ZpcmVEb2N1bWVudENoYW5nZWQoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQkvLyBfZmlyZURvY3VtZW50Q2hhbmdlZChmRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQkvLyBfY2xlYXJEb2N1bWVudEV2ZW50KCk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChOb0NoYW5nZUV2ZW50IGV2ZW50KSB7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0RvY3VtZW50Q2hhbmdlZChldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZkRvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJX2NsZWFyRG9jdW1lbnRFdmVudCgpOwoJfQoKCXByaXZhdGUgdm9pZCBmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoUmVnaW9uQ2hhbmdlZEV2ZW50IGV2ZW50KSB7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0RvY3VtZW50Q2hhbmdlZChldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZkRvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJX2NsZWFyRG9jdW1lbnRFdmVudCgpOwoJfQoKCXByaXZhdGUgdm9pZCBmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoUmVnaW9uc1JlcGxhY2VkRXZlbnQgZXZlbnQpIHsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCW5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzRG9jdW1lbnRDaGFuZ2VkKGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfY2xlYXJEb2N1bWVudEV2ZW50KCk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCBldmVudCkgewoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJbm90aWZ5RG9jdW1lbnRQYXJ0aXRpb25lcnNEb2N1bWVudENoYW5nZWQoZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZEb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCV9jbGVhckRvY3VtZW50RXZlbnQoKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGRvY3VtZW50J3MgY29tcGxldGUgdGV4dC4KCSAqLwoJcHVibGljIFN0cmluZyBnZXQoKSB7CgkJcmV0dXJuIGdldFN0b3JlKCkuZ2V0KDAsIGdldExlbmd0aCgpKTsKCX0KCgkvKioKCSAqIFJldHVybnMgbGVuZ3RoIGNoYXJhY3RlcnMgZnJvbSB0aGUgZG9jdW1lbnQncyB0ZXh0IHN0YXJ0aW5nIGZyb20gdGhlCgkgKiBzcGVjaWZpZWQgcG9zaXRpb24uCgkgKiAKCSAqIEB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqIAoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgdGhlIHJhbmdlIGlzIG5vdCB2YWxpZCBpbiB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIFN0cmluZyBnZXQoaW50IG9mZnNldCwgaW50IGxlbmd0aCkgewoJCVN0cmluZyByZXN1bHQgPSBudWxsOwoJCWludCBteUxlbmd0aCA9IGdldExlbmd0aCgpOwoJCWlmICgwID4gb2Zmc2V0KQoJCQlvZmZzZXQgPSAwOwoJCWlmICgwID4gbGVuZ3RoKQoJCQlsZW5ndGggPSAwOwoJCWlmIChvZmZzZXQgKyBsZW5ndGggPiBteUxlbmd0aCkgewoJCQkvLyBmaXJzdCB0cnkgYWRqdXN0aW5nIGxlbmd0aCB0byBmaXQKCQkJaW50IGxlc3NMZW5ndGggPSBteUxlbmd0aCAtIG9mZnNldDsKCQkJaWYgKChsZXNzTGVuZ3RoID49IDApICYmIChvZmZzZXQgKyBsZXNzTGVuZ3RoID09IG15TGVuZ3RoKSkgewoJCQkJbGVuZ3RoID0gbGVzc0xlbmd0aDsKCQkJfQoJCQllbHNlIHsKCQkJCS8vIHNlY29uZCwgdHJ5IG9mZnNldAoJCQkJaW50IG1vcmVPZmZzZXQgPSBteUxlbmd0aCAtIGxlbmd0aDsKCQkJCWlmICgobW9yZU9mZnNldCA+PSAwKSAmJiAobW9yZU9mZnNldCArIGxlbmd0aCA9PSBteUxlbmd0aCkpIHsKCQkJCQlvZmZzZXQgPSBtb3JlT2Zmc2V0OwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJLy8gY2FuIGhhcHBlbiBpZiBteUxlbmd0aCBpcyAwLgoJCQkJCS8vIG5vIGFkanVzdG1lbnQgcG9zc2libGUuCgkJCQkJcmVzdWx0ID0gbmV3IFN0cmluZygpOwoJCQkJfQoJCQl9CgoJCX0KCQlpZiAocmVzdWx0ID09IG51bGwpIHsKCQkJcmVzdWx0ID0gZ2V0U3RvcmUoKS5nZXQob2Zmc2V0LCBsZW5ndGgpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXB1YmxpYyBPYmplY3QgZ2V0QWRhcHRlcihDbGFzcyBhZGFwdGVyKSB7CgkJcmV0dXJuIFBsYXRmb3JtLmdldEFkYXB0ZXJNYW5hZ2VyKCkuZ2V0QWRhcHRlcih0aGlzLCBhZGFwdGVyKTsKCX0KCglJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGdldENhY2hlZERvY3VtZW50UmVnaW9uKCkgewoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVzdWx0ID0gbnVsbDsKCQlpZiAoVVNFX0xPQ0FMX1RIUkVBRCkgewoJCQlyZXN1bHQgPSBmQ3VycmVudERvY3VtbmV0UmVnaW9uQ2FjaGUuZ2V0KCk7CgkJfQoJCWVsc2UgewoJCQlyZXN1bHQgPSBjYWNoZWREb2N1bWVudFJlZ2lvbjsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2dldENoYXIKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHBvc2l0aW9uIGlzIG5vdCBhIHZhbGlkIHJhbmdlIGluIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgY2hhciBnZXRDaGFyKGludCBwb3MpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJY2hhciByZXN1bHQgPSAweDAwOwoJCXRyeSB7CgkJCXJlc3VsdCA9IGdldFN0b3JlKCkuZ2V0KHBvcyk7CgkJfQoJCWNhdGNoIChJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uIGUpIHsKCQkJdGhyb3cgbmV3IEJhZExvY2F0aW9uRXhjZXB0aW9uKGUuZ2V0TG9jYWxpemVkTWVzc2FnZSgpKTsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIHR5cGUgb2YgdGhlIGRvY3VtZW50IHBhcnRpdGlvbiBjb250YWluaW5nIHRoZSBnaXZlbgoJICogY2hhcmFjdGVyIHBvc2l0aW9uLgoJICovCglwdWJsaWMgU3RyaW5nIGdldENvbnRlbnRUeXBlKGludCBvZmZzZXQpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldERvY3VtZW50UGFydGl0aW9uZXIoKS5nZXRDb250ZW50VHlwZShvZmZzZXQpOwoJfQoKCglwdWJsaWMgU3RyaW5nIGdldENvbnRlbnRUeXBlKFN0cmluZyBwYXJ0aXRpb25pbmcsIGludCBvZmZzZXQsIGJvb2xlYW4gcHJlZmVyT3BlblBhcnRpdGlvbnMpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiwgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIHsKCQlpZiAoKDAgPiBvZmZzZXQpIHx8IChvZmZzZXQgPiBnZXRMZW5ndGgoKSkpCgkJCXRocm93IG5ldyBCYWRMb2NhdGlvbkV4Y2VwdGlvbigpOwoKCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lciA9IGdldERvY3VtZW50UGFydGl0aW9uZXIocGFydGl0aW9uaW5nKTsKCgkJaWYgKHBhcnRpdGlvbmVyIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKQoJCQlyZXR1cm4gKChJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjIpIHBhcnRpdGlvbmVyKS5nZXRDb250ZW50VHlwZShvZmZzZXQsIHByZWZlck9wZW5QYXJ0aXRpb25zKTsKCQllbHNlIGlmIChwYXJ0aXRpb25lciAhPSBudWxsKQoJCQlyZXR1cm4gcGFydGl0aW9uZXIuZ2V0Q29udGVudFR5cGUob2Zmc2V0KTsKCQllbHNlIGlmIChJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HLmVxdWFscyhwYXJ0aXRpb25pbmcpKQoJCQlyZXR1cm4gREVGQVVMVF9DT05URU5UX1RZUEU7CgkJZWxzZQoJCQl0aHJvdyBuZXcgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uKCk7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjZ2V0RGVmYXVsdExpbmVEZWxpbWl0ZXIoKQoJICovCglwdWJsaWMgU3RyaW5nIGdldERlZmF1bHRMaW5lRGVsaW1pdGVyKCkgewoJCQoJCVN0cmluZyBsaW5lRGVsaW1pdGVyPSBudWxsOwoJCQoJCXRyeSB7CgkJCWxpbmVEZWxpbWl0ZXI9IGdldExpbmVEZWxpbWl0ZXIoMCk7CgkJfSBjYXRjaCAoQmFkTG9jYXRpb25FeGNlcHRpb24geCkgewoJCX0KCQoJCWlmIChsaW5lRGVsaW1pdGVyICE9IG51bGwpCgkJCXJldHVybiBsaW5lRGVsaW1pdGVyOwoKCQlpZiAoZkluaXRpYWxMaW5lRGVsaW1pdGVyICE9IG51bGwpCgkJCXJldHVybiBmSW5pdGlhbExpbmVEZWxpbWl0ZXI7CgoJCVN0cmluZyBzeXNMaW5lRGVsaW1pdGVyPSBTeXN0ZW0uZ2V0UHJvcGVydHkoImxpbmUuc2VwYXJhdG9yIik7IC8vJE5PTi1OTFMtMSQKCQlTdHJpbmdbXSBkZWxpbWl0ZXJzPSBnZXRMZWdhbExpbmVEZWxpbWl0ZXJzKCk7CgkJQXNzZXJ0LmlzVHJ1ZShkZWxpbWl0ZXJzLmxlbmd0aCA+IDApOwoJCWZvciAoaW50IGk9IDA7IGkgPCBkZWxpbWl0ZXJzLmxlbmd0aDsgaSsrKSB7CgkJCWlmIChkZWxpbWl0ZXJzW2ldLmVxdWFscyhzeXNMaW5lRGVsaW1pdGVyKSkgewoJCQkJbGluZURlbGltaXRlcj0gc3lzTGluZURlbGltaXRlcjsKCQkJCWJyZWFrOwoJCQl9CgkJfQoJCQoJCWlmIChsaW5lRGVsaW1pdGVyID09IG51bGwpCgkJCWxpbmVEZWxpbWl0ZXI9IGRlbGltaXRlcnNbMF07CgkKCQlyZXR1cm4gbGluZURlbGltaXRlcjsKCQkKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGRvY3VtZW50J3MgcGFydGl0aW9uZXIuCgkgKiAKCSAqIEBzZWUgSURvY3VtZW50UGFydGl0aW9uZXIKCSAqLwoJcHVibGljIElEb2N1bWVudFBhcnRpdGlvbmVyIGdldERvY3VtZW50UGFydGl0aW9uZXIoKSB7CgkJcmV0dXJuIGdldERvY3VtZW50UGFydGl0aW9uZXIoSURvY3VtZW50RXh0ZW5zaW9uMy5ERUZBVUxUX1BBUlRJVElPTklORyk7Cgl9CgoKCXB1YmxpYyBJRG9jdW1lbnRQYXJ0aXRpb25lciBnZXREb2N1bWVudFBhcnRpdGlvbmVyKFN0cmluZyBwYXJ0aXRpb25pbmcpIHsKCgkJSURvY3VtZW50UGFydGl0aW9uZXIgZG9jdW1lbnRQYXJ0aXRpb25lciA9IG51bGw7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyAhPSBudWxsKSB7CgkJCWRvY3VtZW50UGFydGl0aW9uZXIgPSAoSURvY3VtZW50UGFydGl0aW9uZXIpIGZEb2N1bWVudFBhcnRpdGlvbmVycy5nZXQocGFydGl0aW9uaW5nKTsKCQl9CgkJcmV0dXJuIGRvY3VtZW50UGFydGl0aW9uZXI7Cgl9CgoJcHVibGljIEVuY29kaW5nTWVtZW50byBnZXRFbmNvZGluZ01lbWVudG8oKSB7CgkJcmV0dXJuIGVuY29kaW5nTWVtZW50bzsKCX0KCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBnZXRGaXJzdFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbigpIHsKCQkvLyBzaG91bGQgd2UgdXBkYXRlIGNhY2hlZE5vZGU/CgkJLy8gV2Ugc2hvdWxkIHRvIGtlZXAgY29uc2lzdGVudCBwaGlsb3NvcGh5IG9mIHJlbWVtYmVyaW5nIGxhc3QKCQkvLyByZXF1ZXN0ZWQgcG9zaXRpb24sCgkJLy8gZm9yIGVmZmljaWVuY3kuCgkJc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oZmlyc3REb2N1bWVudFJlZ2lvbik7CgkJcmV0dXJuIGZpcnN0RG9jdW1lbnRSZWdpb247Cgl9CgoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZ2V0TGFzdFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbigpIHsKCQkvLyBzaG91bGQgd2UgdXBkYXRlIGNhY2hlZE5vZGU/CgkJLy8gV2Ugc2hvdWxkIHRvIGtlZXAgY29uc2lzdGVudCBwaGlsb3NvcGh5IG9mIHJlbWVtYmVyaW5nIGxhc3QKCQkvLyByZXF1ZXN0ZWQgcG9zaXRpb24sCgkJLy8gZm9yIGVmZmljaWVuY3kuCgkJc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24obGFzdERvY3VtZW50UmVnaW9uKTsKCQlyZXR1cm4gbGFzdERvY3VtZW50UmVnaW9uOwoJfQoKCS8qCgkgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBwYXJ0aXRpb25zCgkgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgkgKi8KCXB1YmxpYyBTdHJpbmdbXSBnZXRMZWdhbENvbnRlbnRUeXBlcygpIHsKCQlTdHJpbmdbXSByZXN1bHQgPSBudWxsOwoJCXRyeSB7CgkJCXJlc3VsdCA9IGdldExlZ2FsQ29udGVudFR5cGVzKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcpOwoJCX0KCQljYXRjaCAoQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIGUpIHsKCQkJLy8gaW1wb3NzaWJsZSBpbiB0aGlzIGNvbnRleHQKCQkJdGhyb3cgbmV3IEVycm9yKGUpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXB1YmxpYyBTdHJpbmdbXSBnZXRMZWdhbENvbnRlbnRUeXBlcyhTdHJpbmcgcGFydGl0aW9uaW5nKSB0aHJvd3MgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIHsKCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lciA9IGdldERvY3VtZW50UGFydGl0aW9uZXIocGFydGl0aW9uaW5nKTsKCQlpZiAocGFydGl0aW9uZXIgIT0gbnVsbCkKCQkJcmV0dXJuIHBhcnRpdGlvbmVyLmdldExlZ2FsQ29udGVudFR5cGVzKCk7CgkJaWYgKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcuZXF1YWxzKHBhcnRpdGlvbmluZykpCgkJCXJldHVybiBuZXcgU3RyaW5nW117REVGQVVMVF9DT05URU5UX1RZUEV9OwoJCXRocm93IG5ldyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24oKTsKCX0KCgkvKgoJICogLS0tLS0tLS0tLS0tLS0tLS0tIGxpbmUgZGVsaW1pdGVyIGNvbnZlcnNpb24KCSAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoJICovCglwdWJsaWMgU3RyaW5nW10gZ2V0TGVnYWxMaW5lRGVsaW1pdGVycygpIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldExlZ2FsTGluZURlbGltaXRlcnMoKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2dldExlbmd0aAoJICovCglwdWJsaWMgaW50IGdldExlbmd0aCgpIHsKCQlyZXR1cm4gZ2V0U3RvcmUoKS5nZXRMZW5ndGgoKTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkRG9jdW1lbnQjZ2V0TGluZURlbGltaXRlcigpCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0TGluZURlbGltaXRlcigpIHsKCQlyZXR1cm4gZ2V0RGVmYXVsdExpbmVEZWxpbWl0ZXIoKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGxpbmUgZGVsaW1pdGVyIG9mIHRoYXQgbGluZQoJICogCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiB0aGUgbGluZSBudW1iZXIgaXMgaW52YWxpZCBpbiB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIFN0cmluZyBnZXRMaW5lRGVsaW1pdGVyKGludCBsaW5lKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lRGVsaW1pdGVyKGxpbmUpOwoJfQoKCS8qKgoJICogUmV0dXJucyBhIGRlc2NyaXB0aW9uIG9mIHRoZSBzcGVjaWZpZWQgbGluZS4gVGhlIGxpbmUgaXMgZGVzY3JpYmVkIGJ5CgkgKiBpdHMgb2Zmc2V0IGFuZCBpdHMgbGVuZ3RoIGV4Y2x1ZGluZyB0aGUgbGluZSdzIGRlbGltaXRlci4KCSAqIAoJICogQHBhcmFtIGxpbmUKCSAqICAgICAgICAgICAgdGhlIGxpbmUgb2YgaW50ZXJlc3QKCSAqIEByZXR1cm4gYSBsaW5lIGRlc2NyaXB0aW9uCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBpZiB0aGUgbGluZSBudW1iZXIgaXMgaW52YWxpZCBpbiB0aGlzIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklSZWdpb24gZ2V0TGluZUluZm9ybWF0aW9uKGludCBsaW5lKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lSW5mb3JtYXRpb24obGluZSk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGEgZGVzY3JpcHRpb24gb2YgdGhlIGxpbmUgYXQgdGhlIGdpdmVuIG9mZnNldC4gVGhlIGRlc2NyaXB0aW9uCgkgKiBjb250YWlucyB0aGUgb2Zmc2V0IGFuZCB0aGUgbGVuZ3RoIG9mIHRoZSBsaW5lIGV4Y2x1ZGluZyB0aGUgbGluZSdzCgkgKiBkZWxpbWl0ZXIuCgkgKiAKCSAqIEBwYXJhbSBvZmZzZXQKCSAqICAgICAgICAgICAgdGhlIG9mZnNldCB3aG9zZSBsaW5lIHNob3VsZCBiZSBkZXNjcmliZWQKCSAqIEByZXR1cm4gYSByZWdpb24gZGVzY3JpYmluZyB0aGUgbGluZQoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgaWYgb2Zmc2V0IGlzIGludmFsaWQgaW4gdGhpcyBkb2N1bWVudAoJICovCglwdWJsaWMgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JUmVnaW9uIGdldExpbmVJbmZvcm1hdGlvbk9mT2Zmc2V0KGludCBvZmZzZXQpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldExpbmVJbmZvcm1hdGlvbk9mT2Zmc2V0KG9mZnNldCk7Cgl9CgoJLyoKCSAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gbGluZSBpbmZvcm1hdGlvbgoJICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCSAqLwoJcHVibGljIGludCBnZXRMaW5lTGVuZ3RoKGludCBsaW5lKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lTGVuZ3RoKGxpbmUpOwoJfQoKCS8qKgoJICogRGV0ZXJtaW5lcyB0aGUgb2Zmc2V0IG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgdGhlIGdpdmVuIGxpbmUuCgkgKiAKCSAqIEBwYXJhbSBsaW5lCgkgKiAgICAgICAgICAgIHRoZSBsaW5lIG9mIGludGVyZXN0CgkgKiBAcmV0dXJuIHRoZSBkb2N1bWVudCBvZmZzZXQKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIHRoZSBsaW5lIG51bWJlciBpcyBpbnZhbGlkIGluIHRoaXMgZG9jdW1lbnQKCSAqLwoJcHVibGljIGludCBnZXRMaW5lT2Zmc2V0KGludCBsaW5lKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lT2Zmc2V0KGxpbmUpOwoJfQoKCXB1YmxpYyBpbnQgZ2V0TGluZU9mT2Zmc2V0KGludCBvZmZzZXQpIHsKCQlpbnQgcmVzdWx0ID0gLTE7CgkJdHJ5IHsKCQkJcmVzdWx0ID0gZ2V0VHJhY2tlcigpLmdldExpbmVOdW1iZXJPZk9mZnNldChvZmZzZXQpOwoJCX0KCQljYXRjaCAoQmFkTG9jYXRpb25FeGNlcHRpb24gZSkgewoJCQlpZiAoTG9nZ2VyLkRFQlVHX0RPQ1VNRU5UKQoJCQkJTG9nZ2VyLmxvZyhMb2dnZXIuSU5GTywgIkRldi4gUHJvZ3JhbSBJbmZvIE9ubHk6IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmdldExpbmVPZk9mZnNldDogb2Zmc2V0IG91dCBvZiByYW5nZSwgemVybyBhc3N1bWVkLiBvZmZzZXQgPSAiICsgb2Zmc2V0LCBlKTsgLy8kTk9OLU5MUy0xJCAvLyROT04tTkxTLTIkCgkJCXJlc3VsdCA9IDA7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgbGluZXMgaW4gdGhpcyBkb2N1bWVudAoJICogCgkgKiBAcmV0dXJuIHRoZSBudW1iZXIgb2YgbGluZXMgaW4gdGhpcyBkb2N1bWVudAoJICovCglwdWJsaWMgaW50IGdldE51bWJlck9mTGluZXMoKSB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXROdW1iZXJPZkxpbmVzKCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgbGluZXMgd2hpY2ggYXJlIG9jY3VwaWVkIGJ5IGEgZ2l2ZW4gdGV4dCByYW5nZS4KCSAqIAoJICogQHBhcmFtIG9mZnNldAoJICogICAgICAgICAgICB0aGUgb2Zmc2V0IG9mIHRoZSBzcGVjaWZpZWQgdGV4dCByYW5nZQoJICogQHBhcmFtIGxlbmd0aAoJICogICAgICAgICAgICB0aGUgbGVuZ3RoIG9mIHRoZSBzcGVjaWZpZWQgdGV4dCByYW5nZQoJICogQHJldHVybiB0aGUgbnVtYmVyIG9mIGxpbmVzIG9jY3VwaWVkIGJ5IHRoZSBzcGVjaWZpZWQgcmFuZ2UKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIHNwZWNpZmllZCByYW5nZSBpcyBpbnZhbGlkIGluIHRoaXMgdHJhY2tlcgoJICovCglwdWJsaWMgaW50IGdldE51bWJlck9mTGluZXMoaW50IG9mZnNldCwgaW50IGxlbmd0aCkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TnVtYmVyT2ZMaW5lcyhvZmZzZXQsIGxlbmd0aCk7Cgl9CgoJLyoqCgkgKiBUaGlzIGlzIHB1YmxpYywgdGVtcG9yYXJpbHksIGZvciB1c2UgYnkgdGFnIGxpYiBjbGFzc2VzLgoJICovCglwdWJsaWMgUmVnaW9uUGFyc2VyIGdldFBhcnNlcigpIHsKCQlpZiAoZlBhcnNlciA9PSBudWxsKSB7CgkJCXRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmdldFBhcnNlci4gUGFyc2VyIG5lZWRzIHRvIGJlIHNldCBiZWZvcmUgdXNlIik7IC8vJE5PTi1OTFMtMSQKCQl9CgkJcmV0dXJuIGZQYXJzZXI7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBkb2N1bWVudCBwYXJ0aXRpb24gaW4gd2hpY2ggdGhlIHBvc2l0aW9uIGlzIGxvY2F0ZWQuIFRoZQoJICogcGFydGl0aW9uIGlzIHNwZWNpZmllZCBhcyB0eXBlZCByZWdpb24uCgkgKi8KCXB1YmxpYyBJVHlwZWRSZWdpb24gZ2V0UGFydGl0aW9uKGludCBvZmZzZXQpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJSVR5cGVkUmVnaW9uIHBhcnRpdGlvbiA9IG51bGw7CgkJdHJ5IHsKCQkJcGFydGl0aW9uID0gZ2V0UGFydGl0aW9uKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcsIG9mZnNldCwgZmFsc2UpOwoJCX0KCQljYXRjaCAoQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIGUpIHsKCQkJdGhyb3cgbmV3IEVycm9yKGUpOwoJCX0KCQlpZiAocGFydGl0aW9uID09IG51bGwpIHsKCQkJdGhyb3cgbmV3IEVycm9yKCk7CgkJfQoJCXJldHVybiBwYXJ0aXRpb247Cgl9CgoKCXB1YmxpYyBJVHlwZWRSZWdpb24gZ2V0UGFydGl0aW9uKFN0cmluZyBwYXJ0aXRpb25pbmcsIGludCBvZmZzZXQsIGJvb2xlYW4gcHJlZmVyT3BlblBhcnRpdGlvbnMpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiwgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIHsKCQlpZiAoKDAgPiBvZmZzZXQpIHx8IChvZmZzZXQgPiBnZXRMZW5ndGgoKSkpCgkJCXRocm93IG5ldyBCYWRMb2NhdGlvbkV4Y2VwdGlvbigpOwoJCUlUeXBlZFJlZ2lvbiByZXN1bHQgPSBudWxsOwoKCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lciA9IGdldERvY3VtZW50UGFydGl0aW9uZXIocGFydGl0aW9uaW5nKTsKCgkJaWYgKHBhcnRpdGlvbmVyIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKSB7CgkJCXJlc3VsdCA9ICgoSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKSBwYXJ0aXRpb25lcikuZ2V0UGFydGl0aW9uKG9mZnNldCwgcHJlZmVyT3BlblBhcnRpdGlvbnMpOwoJCX0KCQllbHNlIGlmIChwYXJ0aXRpb25lciAhPSBudWxsKSB7CgkJCXJlc3VsdCA9IHBhcnRpdGlvbmVyLmdldFBhcnRpdGlvbihvZmZzZXQpOwoJCX0KCQllbHNlIGlmIChJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HLmVxdWFscyhwYXJ0aXRpb25pbmcpKSB7CgkJCXJlc3VsdCA9IG5ldyBUeXBlZFJlZ2lvbigwLCBnZXRMZW5ndGgoKSwgREVGQVVMVF9DT05URU5UX1RZUEUpOwoJCX0KCQllbHNlCgkJCXRocm93IG5ldyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24oKTsKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCglwdWJsaWMgU3RyaW5nW10gZ2V0UGFydGl0aW9uaW5ncygpIHsKCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzID09IG51bGwpCgkJCXJldHVybiBuZXcgU3RyaW5nWzBdOwoJCVN0cmluZ1tdIHBhcnRpdGlvbmluZ3MgPSBuZXcgU3RyaW5nW2ZEb2N1bWVudFBhcnRpdGlvbmVycy5zaXplKCldOwoJCWZEb2N1bWVudFBhcnRpdGlvbmVycy5rZXlTZXQoKS50b0FycmF5KHBhcnRpdGlvbmluZ3MpOwoJCXJldHVybiBwYXJ0aXRpb25pbmdzOwoJfQoKCS8qKgoJICogUmV0dXJucyBhbGwgcG9zaXRpb24gY2F0ZWdvcmllcyBhZGRlZCB0byB0aGlzIGRvY3VtZW50LgoJICovCglwdWJsaWMgU3RyaW5nW10gZ2V0UG9zaXRpb25DYXRlZ29yaWVzKCkgewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5nZXRQb3NpdGlvbkNhdGVnb3JpZXMoKTsKCX0KCgkvKioKCSAqIEByZXR1cm4gUmV0dXJucyB0aGUgcG9zaXRpb25NYW5hZ2VyLgoJICovCglwcml2YXRlIEdlbmVyaWNQb3NpdGlvbk1hbmFnZXIgZ2V0UG9zaXRpb25NYW5hZ2VyKCkgewoJCWlmIChmUG9zaXRpb25NYW5hZ2VyID09IG51bGwpIHsKCQkJZlBvc2l0aW9uTWFuYWdlciA9IG5ldyBHZW5lcmljUG9zaXRpb25NYW5hZ2VyKHRoaXMpOwoJCX0KCQlyZXR1cm4gZlBvc2l0aW9uTWFuYWdlcjsKCX0KCgkvKioKCSAqIFJldHVybnMgYWxsIFBvc2l0aW9ucyBvZiB0aGUgZ2l2ZW4gcG9zaXRpb24gY2F0ZWdvcnkuCgkgKiAKCSAqIEBleGNlcHRpb24gQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgY2F0ZWdvcnkgaXMgbm90IGRlZmluZWQgZm9yIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgUG9zaXRpb25bXSBnZXRQb3NpdGlvbnMoU3RyaW5nIGNhdGVnb3J5KSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0UG9zaXRpb25NYW5hZ2VyKCkuZ2V0UG9zaXRpb25zKGNhdGVnb3J5KTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2dldFBvc2l0aW9uVXBkYXRlcnMKCSAqLwoJcHVibGljIElQb3NpdGlvblVwZGF0ZXJbXSBnZXRQb3NpdGlvblVwZGF0ZXJzKCkgewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5nZXRQb3NpdGlvblVwZGF0ZXJzKCk7Cgl9CgoJLyoqCgkgKiBUaGlzIG1ldGhvZCBjYW4gcmV0dXJuIG51bGwsIHdoaWNoIGlzIHRoZSBjYXNlIGlmIHRoZSBvZmZzZXQgaXMganVzdAoJICogYmVmb3JlIG9yIGp1c3QgYWZ0ZXIgdGhlIGV4aXN0aW5nIHRleHQuIENvbXBhcmUgd2l0aAoJICogZ2V0Tm9kZUF0Q2hhcmFjdGVyT2Zmc2V0LgoJICovCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBnZXRSZWdpb25BdENoYXJhY3Rlck9mZnNldChpbnQgb2Zmc2V0KSB7CgkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZXN1bHQgPSBudWxsOwoKCQkvLyBGSVhNRTogbmVlZCB0byBzeW5jaCBvbiAnY2FjaGVkUmVnaW9uJyAoYnV0IHNpbmNlIHRoYXQncyBhCgkJLy8gY29uc3RhbnRseSBjaGFuZ2luZyBvYmplY3QsIHdlCgkJLy8gY2FuJ3QsIHNvIG5lZWQgdG8gYWRkIGEgInJlZ2lvbl9sb2NrIiBvYmplY3QsIGFuZCB1c2UgaXQgaGVyZSwgYW5kCgkJLy8gaW4gcmUtcGFyc2VyLgoJCS8vIE9oLCBhbmQgbmVlZCB0byBtYWtlIHN1cmUsIGFmdGVyIHN5bmNoLCB0aGF0IHRoZSByZWdpb24gaXMgbm90CgkJLy8gZGVsZXRlZCwgYW5kIGlmIHNvLCBJIGd1ZXNzIGdvIGJhY2sKCQkvLyB0byB0aGUgYmVnaW5uaW5nIQoKCQkvLyBjYWNoZWQgbm9kZSBjYW4gYmUgbnVsbCB3aGVuIGRvY3VtZW50IGlzIGVtcHR5CgkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBwb3RlbnRpYWxDYWNoZWRSZWdpb24gPSBnZXRDYWNoZWREb2N1bWVudFJlZ2lvbigpOwoJCWlmIChwb3RlbnRpYWxDYWNoZWRSZWdpb24gIT0gbnVsbCkgewoKCQkJLy8gCgoJCQkvLyBpZiB3ZSBhbHJlYWR5IGhhdmUgdGhlIHJpZ2h0IG5vZGUsIHJldHVybiB0aGF0LgoJCQlpZiAocG90ZW50aWFsQ2FjaGVkUmVnaW9uLmNvbnRhaW5zT2Zmc2V0KG9mZnNldCkpIHsKCQkJCXJlc3VsdCA9IHBvdGVudGlhbENhY2hlZFJlZ2lvbjsKCQkJfQoJCQllbHNlIHsKCQkJCS8vIGZpcnN0LCBmaW5kIG91dCB3aGF0IGRpcmVjdGlvbiB0byBnbywgcmVsYXRpdmUgdG8KCQkJCS8vIGNhY2hlZE5vZGUuCgkJCQkvLyBuZWdhdGl2ZSBtZWFucyAidG93YXJkcyB0aGUgZnJvbnQiIG9mIHRoZSBmaWxlLAoJCQkJLy8gcG9zdGl0aXZlCgkJCQkvLyBtZWFucwoJCQkJLy8gdG93YXJkcyB0aGUgZW5kLgoJCQkJaW50IGRpcmVjdGlvbiA9IG9mZnNldCAtIHBvdGVudGlhbENhY2hlZFJlZ2lvbi5nZXRTdGFydCgpOwoJCQkJaWYgKGRpcmVjdGlvbiA8IDApIHsKCQkJCQkvLyBzZWFyY2ggdG93YXJkcyBiZWdpbm5pbmcKCQkJCQl3aGlsZSAoIXBvdGVudGlhbENhY2hlZFJlZ2lvbi5jb250YWluc09mZnNldChvZmZzZXQpKSB7CgkJCQkJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gdGVtcE5vZGUgPSBwb3RlbnRpYWxDYWNoZWRSZWdpb24uZ2V0UHJldmlvdXMoKTsKCQkJCQkJaWYgKHRlbXBOb2RlID09IG51bGwpIHsKCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJcG90ZW50aWFsQ2FjaGVkUmVnaW9uID0gdGVtcE5vZGU7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCQllbHNlIHsKCQkJCQkvLyBzZWFyY2ggdG93YXJkcyBlbmQKCQkJCQkvLyBUaGVyZSBpcyBhIGxlZ2l0YW1hdCBjb25kaXRpb24gd2hlcmUgdGhlCgkJCQkJLy8gb2Zmc2V0IHdpbGwgbm90IGJlIGNvbnRhaW5lZCBpbiBhbnkgbm9kZSwKCQkJCQkvLyB3aGljaCBpcyBpZiB0aGUgb2Zmc2V0IGlzIGp1c3QgcGFzdCB0aGUgbGFzdAoJCQkJCS8vIGNoYXJhY3RlciBvZiB0ZXh0LgoJCQkJCS8vIEFuZCwgd2UgbXVzdCBnYXVyZCBhZ2FpbnN0IHNldHRpbmcgY2FjaGVkTm9kZSB0bwoJCQkJCS8vIG51bGwhCgkJCQkJd2hpbGUgKCFwb3RlbnRpYWxDYWNoZWRSZWdpb24uY29udGFpbnNPZmZzZXQob2Zmc2V0KSkgewoJCQkJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHRlbXBOb2RlID0gcG90ZW50aWFsQ2FjaGVkUmVnaW9uLmdldE5leHQoKTsKCQkJCQkJaWYgKHRlbXBOb2RlID09IG51bGwpCgkJCQkJCQlicmVhazsKCQkJCQkJZWxzZQoJCQkJCQkJcG90ZW50aWFsQ2FjaGVkUmVnaW9uID0gdGVtcE5vZGU7CgkJCQkJfQoJCQkJfQoJCQl9CgkJCXJlc3VsdCA9IHBvdGVudGlhbENhY2hlZFJlZ2lvbjsKCQl9CgkJLy8ganVzdCB0byBiZSBkb3VibHkgc3VyZSB3ZSBuZXZlciBhc3NpZ24gbnVsbCB0byBhbiBhbHJlYWR5IHZhbGlkCgkJLy8gY2FjaGVkUmVnaW9uLgoJCS8vIEkgYmVsaWV2ZSBhbnkgdGltZSAncmVzdWx0JyBpcyBudWxsIGF0IHRoaXMgcG9pbnQsIHRoYXQganVzdCBtZWFucwoJCS8vIHdlIGhhdmUgYW4KCQkvLyBlbXB0eSBkb2N1bWVudCwgYW5kIHRoZSBjYWNoZWRSZWdpb24gaXMgYWxyZWFkeSBudWxsLCBidXQgd2UgY2hlY2sKCQkvLyBhbmQgcHJpbnQKCQkvLyB3YXJuaW5nLCBqdXN0IHNvIGR1cmluZyBkZXZlbG9wbWVudCB3ZSBiZSBzdXJlIHdlIG5ldmVyIGFjY2lkZW50bHkKCQkvLyBicmVhayB0aGlzIGFzc3VtcHRpb24uCgkJaWYgKHJlc3VsdCAhPSBudWxsKQoJCQlzZXRDYWNoZWREb2N1bWVudFJlZ2lvbihyZXN1bHQpOwoJCWVsc2UgaWYgKGdldENhY2hlZERvY3VtZW50UmVnaW9uKCkgIT0gbnVsbCkgewoJCQl0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJQcm9ncmFtIEVycm9yOiBubyByZWdpb24gY291bGQgYmUgZm91bmQgdG8gY2FjaGUsIGJ1dCBjYWNoZSB3YXMgbm9uIG51bGwuIEluZGljYXRlcyBjb3JydXB0ZWQgbW9kZWwgb3IgcmVnaW9uIGxpc3QiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJcmV0dXJuIHJlc3VsdDsKCX0KCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbkxpc3QgZ2V0UmVnaW9uTGlzdCgpIHsKCQlDb3JlTm9kZUxpc3QgcmVzdWx0ID0gbnVsbDsKCQlpZiAoZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKSA9PSBudWxsKQoJCQlyZXN1bHQgPSBuZXcgQ29yZU5vZGVMaXN0KG51bGwpOwoJCWVsc2UKCQkJcmVzdWx0ID0gbmV3IENvcmVOb2RlTGlzdChnZXRGaXJzdFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbigpKTsKCgkJcmV0dXJuIHJlc3VsdDsKCX0KCgoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25bXSBnZXRTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zKCkgewoJCXJldHVybiBnZXRTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zKDAsIGdldExlbmd0aCgpKTsKCX0KCgkvKioKCSAqIDxwPgoJICogSW4gdGhlIGNhc2Ugb2YgMCBsZW5ndGgsIHRoZSA8Y29kZT5JU3RydWN0dXJlZERvY3VtZW50UmVnaW9uPC9jb2RlPgoJICogYXQgdGhlIGNoYXJhY3RlciBvZmZzZXQgaXMgcmV0dXJlbmVkLiBJbiBvdGhlciB3b3JkcywgdGhlIHJlZ2lvbiB0byB0aGUKCSAqIHJpZ2h0IG9mIHRoZSBjYXJldCBpcyByZXR1cm5lZC4gZXhjZXB0IGZvciBhdCB0aGUgZW5kIG9mIHRoZSBkb2N1bWVudCwKCSAqIHRoZW4gdGhlIGxhc3QgcmVnaW9uIGlzIHJldHVybmVkLgoJICogPC9wPgoJICogPHA+CgkgKiBPdGhlcndpc2UgYWxsIHRoZSByZWdpb25zICJpbmJldHdlZW4iIHRoZSBpbmRpY2F0ZWQgcmFuZ2UgYXJlIHJldHVybmVkLAoJICogaW5jbHVkaW5nIHRoZSByZWdpb25zIHdoaWNoIG92ZXJsYXAgdGhlIHJlZ2lvbi4KCSAqIDwvcD4KCSAqIAoJICogPGJyPgoJICogZWcuCgkgKiA8cD4KCSAqIDxicj4KCSAqIGVnLgoJICogCgkgKiA8cHJlPgoJICogICAgICAgICAgICAgICAgICAgICAgICAmbHQ7aHRtbCZndDtbJmx0O2hlYWQmZ3Q7Jmx0Oy9oZWFkJmd0O10mbHQ7L2h0bWwmZ3Q7IHJldHVybnMgJmx0O2hlYWQmZ3Q7LCZsdDsvaGVhZCZndDsKCSAqIDwvcHJlPgoJICogICAgPHByZT4KCSAqICAgICAgICAgICAgICAgICAgICAgICAgJmx0O2h0W21sJmd0OyZsdDtoZWFkJmd0OyZsdDsvaGVdYWQmZ3Q7Jmx0Oy9odG1sJmd0OyByZXR1cm5zICZsdDtodG1sJmd0OywmbHQ7aGVhZCZndDssJmx0Oy9oZWFkJmd0OwoJICogPC9wcmU+CgkgKiAKCSAqIDxwcmU+CgkgKiAgICAgICAgICAgICAgICAgICAgICAgICAgJmx0O2h0bWwmZ3Q7WyZsdDtoZWFkJmd0OyZsdDsvaGVhZCZndDtdJmx0Oy9odG1sJmd0OyByZXR1cm5zICZsdDtoZWFkJmd0OywmbHQ7L2hlYWQmZ3Q7CgkgKiA8L3ByZT4KCSAqICAgIDxwcmU+CgkgKiAgICAgICAgICAgICAgICAgICAgICAgICAgJmx0O2h0W21sJmd0OyZsdDtoZWFkJmd0OyZsdDsvaGVdYWQmZ3Q7Jmx0Oy9odG1sJmd0OyByZXR1cm5zICZsdDtodG1sJmd0OywmbHQ7aGVhZCZndDssJmx0Oy9oZWFkJmd0OwoJICogPC9wcmU+CgkgKiAKCSAqIDwvcD4KCSAqLwoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25bXSBnZXRTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zKGludCBzdGFydCwgaW50IGxlbmd0aCkgewoKCQlpZiAobGVuZ3RoIDwgMCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiY2FuJ3QgaGF2ZSBuZWdhdGl2ZSBsZW5ndGgiKTsgLy8kTk9OLU5MUy0xJAoKCQkvLyB0aGlzIHdpbGwgbWFrZSB0aGUgcmlnaHQgZWRnZSBvZiB0aGUgcmFuZ2UgcG9pbnQgaW50byB0aGUgc2VsZWN0aW9uCgkJLy8gZWcuIDxodG1sPls8aGVhZD48L2hlYWQ+XTwvaHRtbD4KCQkvLyB3aWxsIHJldHVybiA8aGVhZD4sPC9oZWFkPiBpbnN0ZWFkIG9mIDxoZWFkPiw8L2hlYWQ+LDwvaHRtbD4KCQlpZiAobGVuZ3RoID4gMCkKCQkJbGVuZ3RoLS07CgoJCUxpc3QgcmVzdWx0cyA9IG5ldyBBcnJheUxpc3QoKTsKCgkJLy8gc3RhcnQgdGhyZWFkIHNhZmUgYmxvY2sKCQl0cnkgewoJCQlhY3F1aXJlTG9jaygpOwoKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBjdXJyZW50UmVnaW9uID0gZ2V0UmVnaW9uQXRDaGFyYWN0ZXJPZmZzZXQoc3RhcnQpOwoJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGVuZFJlZ2lvbiA9IGdldFJlZ2lvbkF0Q2hhcmFjdGVyT2Zmc2V0KHN0YXJ0ICsgbGVuZ3RoKTsKCQkJd2hpbGUgKGN1cnJlbnRSZWdpb24gIT0gZW5kUmVnaW9uICYmIGN1cnJlbnRSZWdpb24gIT0gbnVsbCkgewoJCQkJcmVzdWx0cy5hZGQoY3VycmVudFJlZ2lvbik7CgkJCQljdXJyZW50UmVnaW9uID0gY3VycmVudFJlZ2lvbi5nZXROZXh0KCk7CgkJCX0KCQkJLy8gbmVlZCB0byBhZGQgdGhhdCBsYXN0IGVuZCByZWdpb24KCQkJLy8gY2FuIGJlIG51bGwgaW4gdGhlIGNhc2Ugb2YgYW4gZW1wdHkgZG9jdW1lbnQKCQkJaWYgKGVuZFJlZ2lvbiAhPSBudWxsKQoJCQkJcmVzdWx0cy5hZGQoZW5kUmVnaW9uKTsKCQl9CgkJZmluYWxseSB7CgkJCXJlbGVhc2VMb2NrKCk7CgkJfQoJCS8vIGVuZCB0aHJlYWQgc2FmZSBibG9jawoKCQlyZXR1cm4gKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25bXSkgcmVzdWx0cy50b0FycmF5KG5ldyBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uW3Jlc3VsdHMuc2l6ZSgpXSk7Cgl9CgoJLyoqCgkgKiB3YXMgbWFkZSBwdWJsaWMgZm9yIGVhc2llciB0ZXN0aW5nLiBOb3JtYWxseSBzaG91bGQgbmV2ZXIgYmUgdXNlZCBieQoJICogY2xpZW50IGNvZGVzLgoJICovCglwdWJsaWMgSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgZ2V0UmVQYXJzZXIoKSB7CgkJaWYgKGZSZVBhcnNlciA9PSBudWxsKSB7CgkJCWZSZVBhcnNlciA9IG5ldyBTdHJ1Y3R1cmVkRG9jdW1lbnRSZVBhcnNlcigpOwoJCQlmUmVQYXJzZXIuc2V0U3RydWN0dXJlZERvY3VtZW50KHRoaXMpOwoJCX0KCQlyZXR1cm4gZlJlUGFyc2VyOwoJfQoKCXByaXZhdGUgSVRleHRTdG9yZSBnZXRTdG9yZSgpIHsKCQlBc3NlcnQuaXNOb3ROdWxsKGZTdG9yZSk7CgkJcmV0dXJuIGZTdG9yZTsKCX0KCglwdWJsaWMgU3RyaW5nIGdldFRleHQoKSB7CgkJU3RyaW5nIHJlc3VsdCA9IGdldCgpOwoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBkb2N1bWVudCdzIGxpbmUgdHJhY2tlci4gQXNzdW1lcyB0aGF0IHRoZSBkb2N1bWVudCBoYXMgYmVlbgoJICogaW5pdGlhbGl6ZWQgd2l0aCBhIGxpbmUgdHJhY2tlci4KCSAqIAoJICogQHJldHVybiB0aGUgZG9jdW1lbnQncyBsaW5lIHRyYWNrZXIKCSAqLwoJcHJpdmF0ZSBJTGluZVRyYWNrZXIgZ2V0VHJhY2tlcigpIHsKCQlBc3NlcnQuaXNOb3ROdWxsKGZUcmFja2VyKTsKCQlyZXR1cm4gZlRyYWNrZXI7Cgl9CgoJcHVibGljIElTdHJ1Y3R1cmVkVGV4dFVuZG9NYW5hZ2VyIGdldFVuZG9NYW5hZ2VyKCkgewoJCWlmIChmVW5kb01hbmFnZXIgPT0gbnVsbCkgewoJCQlmVW5kb01hbmFnZXIgPSBuZXcgU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlcigpOwoJCX0KCQlyZXR1cm4gZlVuZG9NYW5hZ2VyOwoJfQoKCXZvaWQgaW5pdGlhbGl6ZUZpcnN0QW5kTGFzdERvY3VtZW50UmVnaW9uKCkgewoJCS8vIGNhY2hlZCBOb2RlIG11c3QgYWxzbyBiZSBmaXJzdCwgYXQgdGhlIGluaXRpYWwgcG9pbnQuIE9ubHkKCQkvLyB2YWxpZAoJCS8vIHRvIGNhbGwgdGhpcyBtZXRob2QgcmlnaHQgYWZ0ZXIgdGhlIGZpcnN0IHBhcnNlLgoJCS8vIAoJCS8vIHdoZW4gc3RhcnRpbmcgYWZyZXNoLCBvdXIgY2FjaGVkTm9kZSBzaG91bGQgYmUgb3VyIGZpcnN0Tm9kZSwKCQkvLyBzbyBiZSBzdXJlIHRvIGluaXRpYWxpemUgdGhlIGZpcnN0Tm9kZQoJCWZpcnN0RG9jdW1lbnRSZWdpb24gPSBnZXRDYWNoZWREb2N1bWVudFJlZ2lvbigpOwoJCS8vIGJlIHN1cmUgdG8gdXNlICdnZXROZXh0JyBmb3IgdGhpcyBpbml0aWFsIGZpbmRpbmcgb2YgdGhlIGxhc3QKCQkvLyBub2RlLAoJCS8vIHNpbmNlIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiBub2RlLmdldExhc3ROb2RlIG1heSBzaW1wbHkgY2FsbAoJCS8vIHN0cnVjdHVyZWREb2N1bWVudC5nZXRMYXN0U3RydWN0dXJlZERvY3VtZW50UmVnaW9uIQoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gYU5vZGUgPSBmaXJzdERvY3VtZW50UmVnaW9uOwoJCWlmIChhTm9kZSA9PSBudWxsKSB7CgkJCS8vIGRlZmVjdCAyNTQ2MDc6IHRvIGhhbmRsZSBlbXB0eSBkb2N1bWVudHMgcmlnaHQsIGlmCgkJCS8vIGZpcnN0bm9kZSBpcwoJCQkvLyBudWxsLCBtYWtlIHN1cmUgbGFzdCBub2RlIGlzIG51bGwgdG9vCgkJCWxhc3REb2N1bWVudFJlZ2lvbiA9IG51bGw7CgkJfQoJCWVsc2UgewoJCQl3aGlsZSAoYU5vZGUgIT0gbnVsbCkgewoJCQkJbGFzdERvY3VtZW50UmVnaW9uID0gYU5vZGU7CgkJCQlhTm9kZSA9IGFOb2RlLmdldE5leHQoKTsKCQkJfQoJCX0KCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2luc2VydFBvc2l0aW9uVXBkYXRlcgoJICovCglwdWJsaWMgdm9pZCBpbnNlcnRQb3NpdGlvblVwZGF0ZXIoSVBvc2l0aW9uVXBkYXRlciB1cGRhdGVyLCBpbnQgaW5kZXgpIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5pbnNlcnRQb3NpdGlvblVwZGF0ZXIodXBkYXRlciwgaW5kZXgpOwoJfQoKCXByaXZhdGUgdm9pZCBpbnRlcm5hbF9hZGRQb3NpdGlvbkNhdGVnb3J5KFN0cmluZyBjYXRlZ29yeSkgewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLmFkZFBvc2l0aW9uQ2F0ZWdvcnkoY2F0ZWdvcnkpOwoJfQoKCXByaXZhdGUgdm9pZCBpbnRlcm5hbF9hZGRQb3NpdGlvblVwZGF0ZXIoSVBvc2l0aW9uVXBkYXRlciB1cGRhdGVyKSB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkuYWRkUG9zaXRpb25VcGRhdGVyKHVwZGF0ZXIpOwoJfQoKCXByaXZhdGUgdm9pZCBpbnRlcm5hbF9zZXRQYXJzZXIoUmVnaW9uUGFyc2VyIG5ld1BhcnNlcikgewoJCWZQYXJzZXIgPSBuZXdQYXJzZXI7Cgl9CgoJU3RyaW5nIGludGVybmFsR2V0KGludCBvZmZzZXQsIGludCBsZW5ndGgpIHsKCQlTdHJpbmcgcmVzdWx0ID0gbnVsbDsKCQkvLyBpbnQgbXlMZW5ndGggPSBnZXRMZW5ndGgoKTsKCQkvLyBpZiAoKDAgPiBvZmZzZXQpIHx8ICgwID4gbGVuZ3RoKSB8fCAob2Zmc2V0ICsgbGVuZ3RoID4gbXlMZW5ndGgpKQoJCS8vIHRocm93IG5ldyBCYWRMb2NhdGlvbkV4Y2VwdGlvbigpOwoJCXJlc3VsdCA9IGdldFN0b3JlKCkuZ2V0KG9mZnNldCwgbGVuZ3RoKTsKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qKgoJICogQHBhcmFtIHJlcXVlc3RlcgoJICogQHBhcmFtIHN0YXJ0CgkgKiBAcGFyYW0gcmVwbGFjZW1lbnRMZW5ndGgKCSAqIEBwYXJhbSBjaGFuZ2VzCgkgKiBAcmV0dXJuCgkgKi8KCXByaXZhdGUgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgaW50ZXJuYWxSZXBsYWNlVGV4dChPYmplY3QgcmVxdWVzdGVyLCBpbnQgc3RhcnQsIGludCByZXBsYWNlbWVudExlbmd0aCwgU3RyaW5nIGNoYW5nZXMsIGJvb2xlYW4gaWdub3JlUmVhZE9ubHlTZXR0aW5ncykgewoJCVN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHJlc3VsdCA9IG51bGw7CgoJCXN0b3BQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJCWlmIChjaGFuZ2VzID09IG51bGwpCgkJCWNoYW5nZXMgPSAiIjsgLy8kTk9OLU5MUy0xJAoJCS8vIAoJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkKCQkJU3lzdGVtLm91dC5wcmludGxuKGdldENsYXNzKCkuZ2V0TmFtZSgpICsgIjo6cmVwbGFjZVRleHQoIiArIHN0YXJ0ICsgIiwiICsgcmVwbGFjZW1lbnRMZW5ndGggKyAiLCIgKyBjaGFuZ2VzICsgIikiKTsgLy8kTk9OLU5MUy00JC8vJE5PTi1OTFMtMyQvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCWlmIChEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudE9ubHkgfHwgRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RSYXdTdHJ1Y3R1cmVkRG9jdW1lbnRPbmx5KSB7CgkJCXN0YXJ0U3RyZWFtVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCX0KCQl0cnkgewoJCQkvLyBOb3RlOiBldmVudCBtdXN0IGJlIGNvbXB1dGVkIGJlZm9yZSAnZmlyZScgbWV0aG9kIGNhbGxlZAoJCQlmRG9jdW1lbnRFdmVudCA9IG5ldyBEb2N1bWVudEV2ZW50KHRoaXMsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCwgY2hhbmdlcyk7CgkJCWZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2VkKCk7CgoJCQl0cnkgewoJCQkJYWNxdWlyZUxvY2soKTsKCgkJCQlpZiAoIWlnbm9yZVJlYWRPbmx5U2V0dGluZ3MgJiYgKGNvbnRhaW5zUmVhZE9ubHkoc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoKSkpIHsKCQkJCQlOb0NoYW5nZUV2ZW50IG5vQ2hhbmdlRXZlbnQgPSBuZXcgTm9DaGFuZ2VFdmVudCh0aGlzLCByZXF1ZXN0ZXIsIGNoYW5nZXMsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCk7CgkJCQkJbm9DaGFuZ2VFdmVudC5yZWFzb24gPSBOb0NoYW5nZUV2ZW50LlJFQURfT05MWV9TVEFURV9DSEFOR0U7CgkJCQkJcmVzdWx0ID0gbm9DaGFuZ2VFdmVudDsKCQkJCX0KCQkJCWVsc2UgewoJCQkJCXJlc3VsdCA9IHVwZGF0ZU1vZGVsKHJlcXVlc3Rlciwgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoLCBjaGFuZ2VzKTsKCQkJCX0KCQkJfQoJCQlmaW5hbGx5IHsKCQkJCXJlbGVhc2VMb2NrKCk7CgkJCX0KCgoJCQlpZiAoRGVidWcucGVyZlRlc3RSYXdTdHJ1Y3R1cmVkRG9jdW1lbnRPbmx5IHx8IERlYnVnLnBlcmZUZXN0KSB7CgkJCQlsb25nIHN0b3BTdHJlYW1UaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgVGltZSBmb3IgSVN0cnVjdHVyZWREb2N1bWVudCByYXcgcmVwbGFjZVRleHQ6ICIgKyAoc3RvcFN0cmVhbVRpbWUgLSBzdGFydFN0cmVhbVRpbWUpKTsgLy8kTk9OLU5MUy0xJAoJCQl9CgkJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkgewoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJldmVudCB0eXBlIHJldHVybmVkIGJ5IHJlcGxhY2VUZXh0V2l0aE5vRGVidWdnaW5nVGhyZWFkOiAiICsgcmVzdWx0KTsgLy8kTk9OLU5MUy0xJAoJCQl9CgkJfQoJCWZpbmFsbHkgewoJCQkvLyBGVVRVUkVfVE9fRE86IGltcGxlbWVudCBjYWxsYmFjayBtZWNoYW5pc20/IHRvIGF2b2lkIGluc3RhbmNlb2YKCQkJLy8gYW5kIGNhc3RpbmcKCQkJLy8gZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50IG11c3QgYmUgY2FsbGVkIGluIG9yZGVyIHRvIGVuZAoJCQkvLyBkb2N1bWVudEFib3V0VG9CZUNoYW5nZWQgc3RhdGUKCgkJCS8vIGluY3JlbWVudCBtb2RpZmljYXRpb24gc3RhbXAgaWYgbW9kaWZpY2F0aW9ucyB3ZXJlIG1hZGUKCQkJaWYgKHJlc3VsdCAhPSBudWxsICYmICEocmVzdWx0IGluc3RhbmNlb2YgTm9DaGFuZ2VFdmVudCkpIHsKCQkJCWZNb2RpZmljYXRpb25TdGFtcCsrOwoJCQkJZk5leHRNb2RpZmljYXRpb25TdGFtcD0gTWF0aC5tYXgoZk1vZGlmaWNhdGlvblN0YW1wLCBmTmV4dE1vZGlmaWNhdGlvblN0YW1wKTsKCQkJfQoKCQkJaWYgKHJlc3VsdCA9PSBudWxsKSB7CgkJCQkvLyByZXN1bHQgc2hvdWxkIG5vdCBiZSBudWxsLCBidXQgaWYgYW4gZXhjZXB0aW9uIHdhcyB0aHJvd24sCgkJCQkvLyBpdCB3aWxsIGJlCgkJCQkvLyBzbyBzZW5kIGEgbm9DaGFuZ2VFdmVudCBhbmQgbG9nIHRoZSBwcm9ibGVtCgkJCQlOb0NoYW5nZUV2ZW50IG5vQ2hhbmdlRXZlbnQgPSBuZXcgTm9DaGFuZ2VFdmVudCh0aGlzLCByZXF1ZXN0ZXIsIGNoYW5nZXMsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCk7CgkJCQlub0NoYW5nZUV2ZW50LnJlYXNvbiA9IE5vQ2hhbmdlRXZlbnQuTk9fRVZFTlQ7CgkJCQlmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQobm9DaGFuZ2VFdmVudCk7CgkJCQlMb2dnZXIubG9nKExvZ2dlci5FUlJPUiwgIlByb2dyYW0gRXJyb3I6IGludmFsaWQgc3RydWN0dXJlZCBkb2N1bWVudCBldmVudCIpOyAvLyROT04tTkxTLTEkCgkJCX0KCQkJZWxzZSB7CgkJCQlpZiAocmVzdWx0IGluc3RhbmNlb2YgUmVnaW9uQ2hhbmdlZEV2ZW50KSB7CgkJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KChSZWdpb25DaGFuZ2VkRXZlbnQpIHJlc3VsdCk7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlpZiAocmVzdWx0IGluc3RhbmNlb2YgUmVnaW9uc1JlcGxhY2VkRXZlbnQpIHsKCQkJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KChSZWdpb25zUmVwbGFjZWRFdmVudCkgcmVzdWx0KTsKCQkJCQl9CgkJCQkJZWxzZSB7CgkJCQkJCWlmIChyZXN1bHQgaW5zdGFuY2VvZiBTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCkgewoJCQkJCQkJLy8gcHJvYmFibHkgbW9yZSBlZmZpY2llbnQgdG8gbWFyayBvbGQgcmVnaW9ucyBhcwoJCQkJCQkJLy8gJ2RlbGV0ZWQnIGF0IHRoZSB0aW1lCgkJCQkJCQkvLyB0aGF0IGFyZSBkZXRlcm1pbmVkIHRvIGJlIGRlbGV0ZWQsIGJ1dCBJJ2xsIGRvCgkJCQkJCQkvLyBoZXJlCgkJCQkJCQkvLyBpbiB0aGVuIGNlbnRyYWwgc3BvdAoJCQkJCQkJLy8gZm9yIHByb2dyYW1taW5nIGVhc2UuCgkJCQkJCQl1cGRhdGVEZWxldGVkRmllbGRzKChTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCkgcmVzdWx0KTsKCQkJCQkJCWZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCgoU3RydWN0dXJlZERvY3VtZW50UmVnaW9uc1JlcGxhY2VkRXZlbnQpIHJlc3VsdCk7CgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQlpZiAocmVzdWx0IGluc3RhbmNlb2YgTm9DaGFuZ2VFdmVudCkgewoJCQkJCQkJCWZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCgoTm9DaGFuZ2VFdmVudCkgcmVzdWx0KTsKCQkJCQkJCX0KCQkJCQkJCWVsc2UgewoJCQkJCQkJCS8vIGlmIGhlcmUsIHRoaXMgbWVhbnMgYSBuZXcgZXZlbnQgd2FzIGNyZWF0ZWQKCQkJCQkJCQkvLyBhbmQgbm90IGhhbmRsZWQgaGVyZQoJCQkJCQkJCS8vIGp1c3Qgc2VuZCBhIG5vIGV2ZW50IHVudGlsIHRoaXMgaXNzdWUgaXMKCQkJCQkJCQkvLyByZXNvbHZlZC4KCQkJCQkJCQlOb0NoYW5nZUV2ZW50IG5vQ2hhbmdlRXZlbnQgPSBuZXcgTm9DaGFuZ2VFdmVudCh0aGlzLCByZXF1ZXN0ZXIsIGNoYW5nZXMsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCk7CgkJCQkJCQkJbm9DaGFuZ2VFdmVudC5yZWFzb24gPSBOb0NoYW5nZUV2ZW50Lk5PX0VWRU5UOwoJCQkJCQkJCWZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChub0NoYW5nZUV2ZW50KTsKCQkJCQkJCQlMb2dnZXIubG9nKExvZ2dlci5JTkZPLCAiUHJvZ3JhbSBFcnJvcjogdW5leHBlY3RlZCBzdHJ1Y3R1cmVkIGRvY3VtZW50IGV2ZW50OiAiICsgcmVzdWx0KTsgLy8kTk9OLU5MUy0xJAoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQl9CgkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudE9ubHkpIHsKCQkJCWxvbmcgc3RvcFN0cmVhbVRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBUb3RhbCBUaW1lIGZvciBJU3RydWN0dXJlZERvY3VtZW50IGV2ZW50IHNpZ25hbGluZy9wcm9jZXNzaW5nIGluIHJlcGxhY2VUZXh0OiAiICsgKHN0b3BTdHJlYW1UaW1lIC0gc3RhcnRTdHJlYW1UaW1lKSk7IC8vJE5PTi1OTFMtMSQKCQkJfQoJCQlyZXN1bWVQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgamF2YS5sYW5nLkNoYXJTZXF1ZW5jZSNsZW5ndGgoKQoJICovCglwdWJsaWMgaW50IGxlbmd0aCgpIHsKCgkJcmV0dXJuIGdldExlbmd0aCgpOwoJfQoJCglwdWJsaWMgdm9pZCBtYWtlUmVhZE9ubHkoaW50IHN0YXJ0T2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJbWFrZVJlYWRPbmx5KHN0YXJ0T2Zmc2V0LCBsZW5ndGgsIGZhbHNlLCBmYWxzZSk7Cgl9CgoJcHVibGljIHZvaWQgbWFrZVJlYWRPbmx5KGludCBzdGFydE9mZnNldCwgaW50IGxlbmd0aCwgYm9vbGVhbiBjYW5JbnNlcnRCZWZvcmUsIGJvb2xlYW4gY2FuSW5zZXJ0QWZ0ZXIpIHsJCgkJLy8gZG9lc24ndCBtYWtlIHNlbnNlIHRvIGhhdmUgYSByZWFkb25seSByZWdpb24gb2YgMCBsZW5ndGgsCgkJLy8gc28gd2UnbGwgaWdub3JlIHRob3NlIHJlcXVlc3RzCgkJaWYgKGxlbmd0aCA8PSAwKQoJCQlyZXR1cm47CgkJU3RyaW5nIGFmZmVjdGVkVGV4dCA9IHRoaXMuZ2V0KHN0YXJ0T2Zmc2V0LCBsZW5ndGgpOwoJCS8vIGEgZG9jdW1lbnQgZXZlbnQgZm9yICJyZWFkIG9ubHkiIGNoYW5nZSAuLi4gbXVzdAoJCS8vIGJlIGZvbGxvd2VkIGJ5ICJubyBjaGFuZ2UiIHN0cnVjdHVyZWREb2N1bWVudCBldmVudAoJCS8vIGZEb2N1bWVudEV2ZW50ID0gbmV3IERvY3VtZW50RXZlbnQodGhpcywgc3RhcnRPZmZzZXQsIGxlbmd0aCwKCQkvLyBhZmZlY3RlZFRleHQpOwoJCWZpcmVSZWFkT25seUFib3V0VG9CZUNoYW5nZWQoKTsKCQkvLyBpZiAoY29udGFpbnNSZWFkT25seShzdGFydE9mZnNldCwgbGVuZ3RoKSkgewoJCS8vIGFkanVzdFJlYWRPbmx5UmVnaW9ucyhzdGFydE9mZnNldCwgbGVuZ3RoKTsKCQkvLyB9IGVsc2UgewoJCS8vIHdlIGNhbiBibGluZGx5IGFkZCBjYXRlZ29yeSwgc2luY2Ugbm8gaGFybSBkb25lIGlmIGFscmVhZHkKCQkvLyBleGlzdHMuCgkJYWRkUG9zaXRpb25DYXRlZ29yeShSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSk7CgkJUG9zaXRpb24gbmV3UG9zaXRpb24gPSBuZXcgUmVhZE9ubHlQb3NpdGlvbihzdGFydE9mZnNldCwgbGVuZ3RoLCBjYW5JbnNlcnRCZWZvcmUpOwoJCXRyeSB7CgkJCWFkZFBvc2l0aW9uKFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZLCBuZXdQb3NpdGlvbik7CgkJCS8vIEZJWE1FOiBuZWVkIHRvIGNoYW5nZSBBUEkgdG8gcGFzcyBpbiByZXF1ZXN0ZXIsIHNvIHRoaXMgZXZlbnQKCQkJLy8gY2FuIGJlCgkJCS8vIGNyZWF0ZWQgY29ycmVjdGx5LCBpbnN0ZWFkIG9mIHVzaW5nIG51bGwuCgkJCU5vQ2hhbmdlRXZlbnQgbm9DaGFuZ2VFdmVudCA9IG5ldyBOb0NoYW5nZUV2ZW50KHRoaXMsIG51bGwsIGFmZmVjdGVkVGV4dCwgc3RhcnRPZmZzZXQsIGxlbmd0aCk7CgkJCW5vQ2hhbmdlRXZlbnQucmVhc29uID0gTm9DaGFuZ2VFdmVudC5SRUFEX09OTFlfU1RBVEVfQ0hBTkdFOwoJCQlmaXJlUmVhZE9ubHlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChub0NoYW5nZUV2ZW50KTsKCQl9CgkJY2F0Y2ggKEJhZExvY2F0aW9uRXhjZXB0aW9uIGUpIHsKCQkJLy8gZm9yIG5vdywgbG9nIGFuZCBpZ25vcmUuIFBlcmhhcHMgbGF0ZXIgd2UKCQkJLy8gY291bGQgYWRqdXN0IHRvIGhhbmRsZSBzb21lIGNhc2VzPwoJCQlMb2dnZXIubG9nRXhjZXB0aW9uKCgiY291bGQgbm90IGNyZWF0ZSByZWFkb25seSByZWdpb24gYXQgIiArIHN0YXJ0T2Zmc2V0ICsgIiB0byAiICsgbGVuZ3RoKSwgZSk7IC8vJE5PTi1OTFMtMSQgLy8kTk9OLU5MUy0yJAoJCX0KCQljYXRjaCAoQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiBlKSB7CgkJCS8vIHNob3VsZCBuZXZlciBvY2N1ciwgc2luY2Ugd2UgYWRkIGNhdGVnb3J5CgkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZSk7CgkJfQoJfQoKCXB1YmxpYyBJU3RydWN0dXJlZERvY3VtZW50IG5ld0luc3RhbmNlKCkgewoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnQgbmV3SW5zdGFuY2UgPSBTdHJ1Y3R1cmVkRG9jdW1lbnRGYWN0b3J5LmdldE5ld1N0cnVjdHVyZWREb2N1bWVudEluc3RhbmNlKGdldFBhcnNlcigpLm5ld0luc3RhbmNlKCkpOwoJCSgoQmFzaWNTdHJ1Y3R1cmVkRG9jdW1lbnQpIG5ld0luc3RhbmNlKS5zZXRSZVBhcnNlcihnZXRSZVBhcnNlcigpLm5ld0luc3RhbmNlKCkpOwoJCWlmIChnZXREb2N1bWVudFBhcnRpdGlvbmVyKCkgaW5zdGFuY2VvZiBTdHJ1Y3R1cmVkVGV4dFBhcnRpdGlvbmVyKSB7CgkJCW5ld0luc3RhbmNlLnNldERvY3VtZW50UGFydGl0aW9uZXIoKChTdHJ1Y3R1cmVkVGV4dFBhcnRpdGlvbmVyKSBnZXREb2N1bWVudFBhcnRpdGlvbmVyKCkpLm5ld0luc3RhbmNlKCkpOwoJCQluZXdJbnN0YW5jZS5nZXREb2N1bWVudFBhcnRpdGlvbmVyKCkuY29ubmVjdChuZXdJbnN0YW5jZSk7CgkJfQoJCW5ld0luc3RhbmNlLnNldExpbmVEZWxpbWl0ZXIoZ2V0TGluZURlbGltaXRlcigpKTsKCQlpZiAoZ2V0RW5jb2RpbmdNZW1lbnRvKCkgIT0gbnVsbCkgewoJCQluZXdJbnN0YW5jZS5zZXRFbmNvZGluZ01lbWVudG8oKEVuY29kaW5nTWVtZW50bykgZ2V0RW5jb2RpbmdNZW1lbnRvKCkuY2xvbmUoKSk7CgkJfQoJCXJldHVybiBuZXdJbnN0YW5jZTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC50ZXh0LklSZWdpb25Db21wYXJpYmxlI3JlZ2lvbk1hdGNoZXMoaW50LAoJICogICAgICBpbnQsIGphdmEubGFuZy5TdHJpbmcpCgkgKi8KCXB1YmxpYyBib29sZWFuIHJlZ2lvbk1hdGNoZXMoaW50IG9mZnNldCwgaW50IGxlbmd0aCwgU3RyaW5nIHN0cmluZ1RvQ29tcGFyZSkgewoJCWJvb2xlYW4gcmVzdWx0ID0gZmFsc2U7CgkJSVRleHRTdG9yZSBzdG9yZSA9IGdldFN0b3JlKCk7CgkJaWYgKHN0b3JlIGluc3RhbmNlb2YgSVJlZ2lvbkNvbXBhcmlibGUpIHsKCQkJcmVzdWx0ID0gKChJUmVnaW9uQ29tcGFyaWJsZSkgc3RvcmUpLnJlZ2lvbk1hdGNoZXMob2Zmc2V0LCBsZW5ndGgsIHN0cmluZ1RvQ29tcGFyZSk7CgkJfQoJCWVsc2UgewoJCQlyZXN1bHQgPSBnZXQob2Zmc2V0LCBsZW5ndGgpLmVxdWFscyhzdHJpbmdUb0NvbXBhcmUpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXB1YmxpYyBib29sZWFuIHJlZ2lvbk1hdGNoZXNJZ25vcmVDYXNlKGludCBvZmZzZXQsIGludCBsZW5ndGgsIFN0cmluZyBzdHJpbmdUb0NvbXBhcmUpIHsKCQlib29sZWFuIHJlc3VsdCA9IGZhbHNlOwoJCUlUZXh0U3RvcmUgc3RvcmUgPSBnZXRTdG9yZSgpOwoJCWlmIChzdG9yZSBpbnN0YW5jZW9mIElSZWdpb25Db21wYXJpYmxlKSB7CgkJCXJlc3VsdCA9ICgoSVJlZ2lvbkNvbXBhcmlibGUpIHN0b3JlKS5yZWdpb25NYXRjaGVzSWdub3JlQ2FzZShvZmZzZXQsIGxlbmd0aCwgc3RyaW5nVG9Db21wYXJlKTsKCQl9CgkJZWxzZSB7CgkJCXJlc3VsdCA9IGdldChvZmZzZXQsIGxlbmd0aCkuZXF1YWxzSWdub3JlQ2FzZShzdHJpbmdUb0NvbXBhcmUpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb24jcmVnaXN0ZXJQb3N0Tm90aWZpY2F0aW9uUmVwbGFjZShvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudExpc3RlbmVyLAoJICogICAgICBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSkKCSAqLwoJcHVibGljIHZvaWQgcmVnaXN0ZXJQb3N0Tm90aWZpY2F0aW9uUmVwbGFjZShJRG9jdW1lbnRMaXN0ZW5lciBvd25lciwgSURvY3VtZW50RXh0ZW5zaW9uLklSZXBsYWNlIHJlcGxhY2UpIHsKCQlpZiAoZkFjY2VwdFBvc3ROb3RpZmljYXRpb25SZXBsYWNlcykgewoJCQlpZiAoZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzID09IG51bGwpCgkJCQlmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMgPSBuZXcgQXJyYXlMaXN0KDEpOwoJCQlmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMuYWRkKG5ldyBSZWdpc3RlcmVkUmVwbGFjZShvd25lciwgcmVwbGFjZSkpOwoJCX0KCX0KCglwcm90ZWN0ZWQgdm9pZCByZWxlYXNlTG9jaygpIHsKCQkvLyBkbyBub3RoaW5nIGhlcmUgaW4gc3VwZXIgY2xhc3MKCX0KCglwdWJsaWMgdm9pZCByZW1vdmVEb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcihJTW9kZWxBYm91dFRvQmVDaGFuZ2VkTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKChmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyAhPSBudWxsKSAmJiAobGlzdGVuZXIgIT0gbnVsbCkpIHsKCQkJCS8vIGlmIGl0cyBub3QgaW4gdGhlIGxpc3RlbmVycywgd2UnbGwgaWdub3JlIHRoZSByZXF1ZXN0CgkJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCQlpbnQgb2xkU2l6ZSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzLmxlbmd0aDsKCQkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgLSAxOwoJCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQkJaW50IGluZGV4ID0gMDsKCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFNpemU7IGkrKykgewoJCQkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnNbaV0gPT0gbGlzdGVuZXIpIHsgLy8gaWdub3JlCgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQkvLyBjb3B5IG9sZCB0byBuZXcgaWYgaXRzIG5vdCB0aGUgb25lIHdlIGFyZQoJCQkJCQkJLy8gcmVtb3ZpbmcKCQkJCQkJCW5ld0xpc3RlbmVyc1tpbmRleCsrXSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzW2ldOwoJCQkJCQl9CgkJCQkJfQoJCQkJCS8vIG5vdyB0aGF0IHdlIGhhdmUgYSBuZXcgYXJyYXksIGxldCdzIHN3aXRjaCBpdCBmb3IgdGhlCgkJCQkJLy8gb2xkCgkJCQkJLy8gb25lCgkJCQkJZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiByZW1vdmVNb2RlbENoYW5nZWRMaXN0ZW5lciBtZXRob2QgY29tbWVudC4KCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXIoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmICgoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMgIT0gbnVsbCkgJiYgKGxpc3RlbmVyICE9IG51bGwpKSB7CgkJCQkvLyBpZiBpdHMgbm90IGluIHRoZSBsaXN0ZW5lcnMsIHdlJ2xsIGlnbm9yZSB0aGUgcmVxdWVzdAoJCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQkJaW50IG9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycy5sZW5ndGg7CgkJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplIC0gMTsKCQkJCQlPYmplY3RbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgT2JqZWN0W25ld1NpemVdOwoJCQkJCWludCBpbmRleCA9IDA7CgkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBvbGRTaXplOyBpKyspIHsKCQkJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzW2ldID09IGxpc3RlbmVyKSB7IC8vIGlnbm9yZQoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJLy8gY29weSBvbGQgdG8gbmV3IGlmIGl0cyBub3QgdGhlIG9uZSB3ZSBhcmUKCQkJCQkJCS8vIHJlbW92aW5nCgkJCQkJCQluZXdMaXN0ZW5lcnNbaW5kZXgrK10gPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVyc1tpXTsKCQkJCQkJfQoJCQkJCX0KCQkJCQkvLyBub3cgdGhhdCB3ZSBoYXZlIGEgbmV3IGFycmF5LCBsZXQncyBzd2l0Y2ggaXQgZm9yIHRoZQoJCQkJCS8vIG9sZAoJCQkJCS8vIG9uZQoJCQkJCWZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJfQoJCQl9CgkJfQoJfQoKCXB1YmxpYyB2b2lkIHJlbW92ZURvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcihJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMgIT0gbnVsbCkgJiYgKGxpc3RlbmVyICE9IG51bGwpKSB7CgkJCQkvLyBpZiBpdHMgbm90IGluIHRoZSBsaXN0ZW5lcnMsIHdlJ2xsIGlnbm9yZSB0aGUgcmVxdWVzdAoJCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJCWludCBvbGRTaXplID0gZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLmxlbmd0aDsKCQkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgLSAxOwoJCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQkJaW50IGluZGV4ID0gMDsKCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFNpemU7IGkrKykgewoJCQkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzW2ldID09IGxpc3RlbmVyKSB7IC8vIGlnbm9yZQoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJLy8gY29weSBvbGQgdG8gbmV3IGlmIGl0cyBub3QgdGhlIG9uZSB3ZSBhcmUKCQkJCQkJCS8vIHJlbW92aW5nCgkJCQkJCQluZXdMaXN0ZW5lcnNbaW5kZXgrK10gPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnNbaV07CgkJCQkJCX0KCQkJCQl9CgkJCQkJLy8gbm93IHRoYXQgd2UgaGF2ZSBhIG5ldyBhcnJheSwgbGV0J3Mgc3dpdGNoIGl0IGZvciB0aGUKCQkJCQkvLyBvbGQKCQkJCQkvLyBvbmUKCQkJCQlmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRMaXN0ZW5lcihJRG9jdW1lbnRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoKGZEb2N1bWVudExpc3RlbmVycyAhPSBudWxsKSAmJiAobGlzdGVuZXIgIT0gbnVsbCkpIHsKCQkJCS8vIGlmIGl0cyBub3QgaW4gdGhlIGxpc3RlbmVycywgd2UnbGwgaWdub3JlIHRoZSByZXF1ZXN0CgkJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZEb2N1bWVudExpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQkJaW50IG9sZFNpemUgPSBmRG9jdW1lbnRMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSAtIDE7CgkJCQkJSURvY3VtZW50TGlzdGVuZXJbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgSURvY3VtZW50TGlzdGVuZXJbbmV3U2l6ZV07CgkJCQkJaW50IGluZGV4ID0gMDsKCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFNpemU7IGkrKykgewoJCQkJCQlpZiAoZkRvY3VtZW50TGlzdGVuZXJzW2ldID09IGxpc3RlbmVyKSB7IC8vIGlnbm9yZQoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJLy8gY29weSBvbGQgdG8gbmV3IGlmIGl0cyBub3QgdGhlIG9uZSB3ZSBhcmUKCQkJCQkJCS8vIHJlbW92aW5nCgkJCQkJCQluZXdMaXN0ZW5lcnNbaW5kZXgrK10gPSBmRG9jdW1lbnRMaXN0ZW5lcnNbaV07CgkJCQkJCX0KCQkJCQl9CgkJCQkJLy8gbm93IHRoYXQgd2UgaGF2ZSBhIG5ldyBhcnJheSwgbGV0J3Mgc3dpdGNoIGl0IGZvciB0aGUKCQkJCQkvLyBvbGQKCQkJCQkvLyBvbmUKCQkJCQlmRG9jdW1lbnRMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJLyoKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnQjcmVtb3ZlRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcihvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCByZW1vdmVEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCUFzc2VydC5pc05vdE51bGwobGlzdGVuZXIpOwoJCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzICE9IG51bGwpCgkJCQlmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMucmVtb3ZlKGxpc3RlbmVyKTsKCQl9Cgl9CgoJLyoqCgkgKiBSZW1vdmVzIHRoZSBnaXZlbiA8Y29kZT5Qb3NpdGlvbjwvY29kZT4gZnJvbSB0aGUgZG9jdW1lbnQncyBkZWZhdWx0CgkgKiBwb3NpdGlvbiBjYXRlZ29yeS4gVGhlIGRlZmF1bHQgcG9zaXRpb24gY2F0ZWdvcnkgaXMgdG8gYmUgZGVmaW5lZCBieQoJICogdGhlIGltcGxlbWVudGVycy4gSWYgdGhlIHBvc2l0aW9uIGlzIG5vdCBwYXJ0IG9mIHRoZSBkb2N1bWVudCdzIGRlZmF1bHQKCSAqIGNhdGVnb3J5IG5vdGhpbmcgaGFwcGVucy4KCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlUG9zaXRpb24oUG9zaXRpb24gcG9zaXRpb24pIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5yZW1vdmVQb3NpdGlvbihwb3NpdGlvbik7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNyZW1vdmVQb3NpdGlvbgoJICogQGV4Y2VwdGlvbiBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiB0aGUgY2F0ZWdvcnkgaXMgbm90IGRlZmluZWQgZm9yIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQb3NpdGlvbihTdHJpbmcgY2F0ZWdvcnksIFBvc2l0aW9uIHBvc2l0aW9uKSB0aHJvd3MgQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkucmVtb3ZlUG9zaXRpb24oY2F0ZWdvcnksIHBvc2l0aW9uKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3JlbW92ZVBvc2l0aW9uQ2F0ZWdvcnkKCSAqIEBleGNlcHRpb24gQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgdGhlIGNhdGVnb3J5IGlzIG5vdCBkZWZpbmVkIGZvciB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlUG9zaXRpb25DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnkpIHRocm93cyBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5yZW1vdmVQb3NpdGlvbkNhdGVnb3J5KGNhdGVnb3J5KTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3JlbW92ZVBvc2l0aW9uVXBkYXRlcgoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQb3NpdGlvblVwZGF0ZXIoSVBvc2l0aW9uVXBkYXRlciB1cGRhdGVyKSB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkucmVtb3ZlUG9zaXRpb25VcGRhdGVyKHVwZGF0ZXIpOwoJfQoKCS8qKgoJICogUmVtb3ZlcyB0aGUgZ2l2ZW4gZG9jdW1lbnQgbGlzdGVuZXIgZnJvbSB0ZWggZG9jdW1lbnQncyBsaXN0IG9mCgkgKiBwcmVub3RpZmllZCBkb2N1bWVudCBsaXN0ZW5lcnMuIElmIHRoZSBsaXN0ZW5lciBpcyBub3QgcmVnaXN0ZXJlZCB3aXRoCgkgKiB0aGUgZG9jdW1lbnQgbm90aGluZyBoYXBwZW5zLgoJICogPHA+CgkgKiAKCSAqIFRoaXMgbWV0aG9kIGlzIG5vdCBmb3IgcHVibGljIHVzZSwgaXQgbWF5IG9ubHkgYmUgY2FsbGVkIGJ5CgkgKiBpbXBsZW1lbnRlcnMgb2YgPGNvZGU+SURvY3VtZW50QWRhcHRlcjwvY29kZT4gYW5kIG9ubHkgaWYgdGhvc2UKCSAqIGltcGxlbWVudGVycyBuZWVkIHRvIGltcGxlbWVudCA8Y29kZT5JRG9jdW1lbnRMaXN0ZW5lcjwvY29kZT4uCgkgKiAKCSAqIEBwYXJhbSBkb2N1bWVudEFkYXB0ZXIKCSAqICAgICAgICAgICAgdGhlIGxpc3RlbmVyIHRvIGJlIHJlbW92ZWQKCSAqIAoJICogQHNlZSAjYWRkUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVyKElEb2N1bWVudExpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXIob3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRMaXN0ZW5lciBkb2N1bWVudEFkYXB0ZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgZG9jdW1lbnRBZGFwdGVyKSkgewoJCQkJaW50IHByZXZpb3VzU2l6ZSA9IGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLmxlbmd0aDsKCQkJCWlmIChwcmV2aW91c1NpemUgPiAxKSB7CgkJCQkJSURvY3VtZW50TGlzdGVuZXJbXSBsaXN0ZW5lcnMgPSBuZXcgSURvY3VtZW50TGlzdGVuZXJbcHJldmlvdXNTaXplIC0gMV07CgkJCQkJaW50IHByZXZpb3VzSW5kZXggPSAwOwoJCQkJCWludCBuZXdJbmRleCA9IDA7CgkJCQkJd2hpbGUgKHByZXZpb3VzSW5kZXggPCBwcmV2aW91c1NpemUpIHsKCQkJCQkJaWYgKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzW3ByZXZpb3VzSW5kZXhdICE9IGRvY3VtZW50QWRhcHRlcikKCQkJCQkJCWxpc3RlbmVyc1tuZXdJbmRleCsrXSA9IGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzW3ByZXZpb3VzSW5kZXhdOwoJCQkJCQlwcmV2aW91c0luZGV4Kys7CgkJCQkJfQoJCQkJCWZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMgPSBudWxsOwoJCQkJfQoJCQl9CgkJfQoJfQoKCS8qKgoJICogVGhpcyBtZXRob2QgaXMgZm9yIElOVEVSTkFMIFVTRSBPTkxZIGFuZCBpcyBOT1QgQVBJLgoJICogCgkgKiBSZWJ1aWxkcyB0aGUgU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGNoYWluIGZyb20gdGhlIGV4aXN0aW5nIHRleHQuCgkgKiBGaWxlQnVmZmVyIHN1cHBvcnQgZG9lcyBub3QgYWxsb3cgY2xpZW50cyB0byBrbm93IHRoZSBkb2N1bWVudCdzCgkgKiBsb2NhdGlvbiBiZWZvcmUgdGhlIHRleHQgY29udGVudHMgYXJlIHNldC4KCSAqIAoJICogQHNlZSBzZXQoU3RyaW5nKQoJICovCglwdWJsaWMgdm9pZCByZXBhcnNlKE9iamVjdCByZXF1ZXN0ZXIpIHsKCQlzdG9wUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCQljbGVhclJlYWRPbmx5KCk7CgoJCWFjcXVpcmVMb2NrKCk7CgkJdHJ5IHsKCQkJQ2hhclNlcXVlbmNlUmVhZGVyIHN1YlNldFRleHRTdG9yZVJlYWRlciA9IG5ldyBDaGFyU2VxdWVuY2VSZWFkZXIoKENoYXJTZXF1ZW5jZSkgZ2V0U3RvcmUoKSwgMCwgZ2V0U3RvcmUoKS5nZXRMZW5ndGgoKSk7CgkJCXJlc2V0UGFyc2VyKHN1YlNldFRleHRTdG9yZVJlYWRlciwgMCk7CgkJCS8vCgkJCXNldENhY2hlZERvY3VtZW50UmVnaW9uKGdldFBhcnNlcigpLmdldERvY3VtZW50UmVnaW9ucygpKTsKCQkJLy8gd2hlbiBzdGFydGluZyBhZnJlc2gsIG91ciBjYWNoZWROb2RlIHNob3VsZCBiZSBvdXIgZmlyc3ROb2RlLAoJCQkvLyBzbyBiZSBzdXJlIHRvIGluaXRpYWxpemUgdGhlIGZpcnN0Tm9kZSBhbmQgbGFzdE5vZGUKCQkJaW5pdGlhbGl6ZUZpcnN0QW5kTGFzdERvY3VtZW50UmVnaW9uKCk7CgkJCVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbkl0ZXJhdG9yLnNldFBhcmVudERvY3VtZW50KGdldENhY2hlZERvY3VtZW50UmVnaW9uKCksIHRoaXMpOwoJCX0KCQlmaW5hbGx5IHsKCQkJcmVsZWFzZUxvY2soKTsKCQl9CgoJCXJlc3VtZVBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCk7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNyZXBsYWNlCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiBwb3NpdGlvbiBpcyBub3QgYSB2YWxpZCByYW5nZSBpbiB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIHZvaWQgcmVwbGFjZShpbnQgcG9zLCBpbnQgbGVuZ3RoLCBTdHJpbmcgc3RyaW5nKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCWlmIChEZWJ1Zy5kaXNwbGF5V2FybmluZ3MpIHsKCQkJU3lzdGVtLm91dC5wcmludGxuKCJOb3RlOiBJU3RydWN0dXJlZERvY3VtZW50OjpyZXBsYWNlKGludCwgaW50LCBTdHJpbmcpIC4uLi4gaXRzIGJldHRlciB0byB1c2UgcmVwbGFjZVRleHQoc291cmNlLCBzdHJpbmcsIGludCwgaW50KSBBUEkgZm9yIHN0cnVjdHVyZWREb2N1bWVudCB1cGRhdGVzIik7IC8vJE5PTi1OTFMtMSQKCQl9CgkJcmVwbGFjZVRleHQodGhpcywgcG9zLCBsZW5ndGgsIHN0cmluZyk7Cgl9CgoJLyoqCgkgKiBSZXBsYWNlIHRoZSB0ZXh0IHdpdGggIm5ld1RleHQiIHN0YXJ0aW5nIGF0IHBvc2l0aW9uICJzdGFydCIgZm9yIGEKCSAqIGxlbmd0aCBvZiAicmVwbGFjZUxlbmd0aCIuCgkgKiA8cD4KCSAqIAoJICogQHBhcmFtIHN0YXJ0CgkgKiAgICAgICAgICAgIHN0YXJ0IG9mZnNldCBvZiB0ZXh0IHRvIHJlcGxhY2UgTm9uZSBvZiB0aGUgb2Zmc2V0cyBpbmNsdWRlCgkgKiAgICAgICAgICAgIGRlbGltaXRlcnMgb2YgcHJlY2VlZGluZyBsaW5lcy4gT2Zmc2V0IDAgaXMgdGhlIGZpcnN0CgkgKiAgICAgICAgICAgIGNoYXJhY3RlciBvZiB0aGUgZG9jdW1lbnQuCgkgKiBAcGFyYW0gcmVwbGFjZUxlbmd0aAoJICogICAgICAgICAgICBzdGFydCBvZmZzZXQgb2YgdGV4dCB0byByZXBsYWNlCgkgKiBAcGFyYW0gbmV3VGV4dAoJICogICAgICAgICAgICBzdGFydCBvZmZzZXQgb2YgdGV4dCB0byByZXBsYWNlCgkgKiAgICAgICAgICAgIDxwPgoJICogICAgICAgICAgICBJbXBsZW1lbnRvcnMgaGF2ZSB0byBub3RpZnkgVGV4dENoYW5nZWQgbGlzdGVuZXJzIGFmdGVyIHRoZQoJICogICAgICAgICAgICBjb250ZW50IGhhcyBiZWVuIHVwZGF0ZWQuIFRoZSBUZXh0Q2hhbmdlZEV2ZW50IHNob3VsZCBiZSBzZXQKCSAqICAgICAgICAgICAgYXMgZm9sbG93czoKCSAqIAoJICogZXZlbnQudHlwZSA9IFNXVC5UZXh0UmVwbGFjZWQgZXZlbnQuc3RhcnQgPSBzdGFydCBvZiB0aGUgcmVwbGFjZWQgdGV4dAoJICogZXZlbnQubnVtUmVwbGFjZWRMaW5lcyA9IG51bWJlciBvZiByZXBsYWNlZCBsaW5lcyBldmVudC5udW1OZXdMaW5lcyA9CgkgKiBudW1iZXIgb2YgbmV3IGxpbmVzIGV2ZW50LnJlcGxhY2VkTGVuZ3RoID0gbGVuZ3RoIG9mIHRoZSByZXBsYWNlZCB0ZXh0CgkgKiBldmVudC5uZXdMZW5ndGggPSBsZW5ndGggb2YgdGhlIG5ldyB0ZXh0CgkgKiAKCSAqIE5PVEU6IG51bU5ld0xpbmVzIGlzIHRoZSBudW1iZXIgb2YgaW5zZXJ0ZWQgbGluZXMgYW5kIG51bVJlcGxhY2VkTGluZXMKCSAqIGlzIHRoZSBudW1iZXIgb2YgZGVsZXRlZCBsaW5lcyBiYXNlZCBvbiB0aGUgY2hhbmdlIHRoYXQgb2NjdXJzCgkgKiB2aXN1YWxseS4gRm9yIGV4YW1wbGU6CgkgKiAKCSAqIHJlcGxhY2VkVGV4dCBuZXdUZXh0IG51bVJlcGxhY2VkTGluZXMgbnVtTmV3TGluZXMgIiIgIlxuIiAwIDEgIlxuXG4iCgkgKiAiYSIgMiAwICJhIiAiXG5cbiIgMCAyCgkgKi8KCS8qKgoJICogT25lIG9mIHRoZSBBUElzIHRvIG1hbmlwdWxhdGUgdGhlIElTdHJ1Y3R1cmVkRG9jdW1lbnQgaW4gdGVybXMgb2YgdGV4dC4KCSAqLwoJcHVibGljIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHJlcGxhY2VUZXh0KE9iamVjdCByZXF1ZXN0ZXIsIGludCBzdGFydCwgaW50IHJlcGxhY2VtZW50TGVuZ3RoLCBTdHJpbmcgY2hhbmdlcykgewoJCXJldHVybiByZXBsYWNlVGV4dChyZXF1ZXN0ZXIsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCwgY2hhbmdlcywgZmFsc2UpOwoJfQoKCXB1YmxpYyBTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCByZXBsYWNlVGV4dChPYmplY3QgcmVxdWVzdGVyLCBpbnQgc3RhcnQsIGludCByZXBsYWNlbWVudExlbmd0aCwgU3RyaW5nIGNoYW5nZXMsIGJvb2xlYW4gaWdub3JlUmVhZE9ubHlTZXR0aW5ncykgewoJCWxvbmcgbW9kaWZpY2F0aW9uU3RhbXA7CgkJCgkJaWYgKHJlcGxhY2VtZW50TGVuZ3RoID09IDAgJiYgKGNoYW5nZXMgPT0gbnVsbCB8fCBjaGFuZ2VzLmxlbmd0aCgpID09IDApKQoJCQltb2RpZmljYXRpb25TdGFtcCA9IGdldE1vZGlmaWNhdGlvblN0YW1wKCk7CgkJZWxzZQoJCQltb2RpZmljYXRpb25TdGFtcCA9IGdldE5leHRNb2RpZmljYXRpb25TdGFtcCgpOwoJCQoJCXJldHVybiByZXBsYWNlVGV4dChyZXF1ZXN0ZXIsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCwgY2hhbmdlcywgaWdub3JlUmVhZE9ubHlTZXR0aW5ncywgbW9kaWZpY2F0aW9uU3RhbXApOwoJfQoJCglwcml2YXRlIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHJlcGxhY2VUZXh0KE9iamVjdCByZXF1ZXN0ZXIsIGludCBzdGFydCwgaW50IHJlcGxhY2VtZW50TGVuZ3RoLCBTdHJpbmcgY2hhbmdlcywgYm9vbGVhbiBpZ25vcmVSZWFkT25seVNldHRpbmdzLCBsb25nIG1vZGlmaWNhdGlvblN0YW1wKSB7CgkJU3RydWN0dXJlZERvY3VtZW50RXZlbnQgZXZlbnQgPSBpbnRlcm5hbFJlcGxhY2VUZXh0KHJlcXVlc3Rlciwgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoLCBjaGFuZ2VzLCBpZ25vcmVSZWFkT25seVNldHRpbmdzKTsKCQlmTW9kaWZpY2F0aW9uU3RhbXAgPSBtb2RpZmljYXRpb25TdGFtcDsKCQlmTmV4dE1vZGlmaWNhdGlvblN0YW1wPSBNYXRoLm1heChmTW9kaWZpY2F0aW9uU3RhbXAsIGZOZXh0TW9kaWZpY2F0aW9uU3RhbXApOwoJCXJldHVybiBldmVudDsKCX0KCgl2b2lkIHJlc2V0UGFyc2VyKGludCBzdGFydE9mZnNldCwgaW50IGVuZE9mZnNldCkgewoKCQlSZWdpb25QYXJzZXIgcGFyc2VyID0gZ2V0UGFyc2VyKCk7CgkJSVRleHRTdG9yZSB0ZXh0U3RvcmUgPSBnZXRTdG9yZSgpOwoJCWlmICh0ZXh0U3RvcmUgaW5zdGFuY2VvZiBDaGFyU2VxdWVuY2UpIHsKCQkJQ2hhclNlcXVlbmNlUmVhZGVyIHN1YlNldFRleHRTdG9yZVJlYWRlciA9IG5ldyBDaGFyU2VxdWVuY2VSZWFkZXIoKENoYXJTZXF1ZW5jZSkgdGV4dFN0b3JlLCBzdGFydE9mZnNldCwgZW5kT2Zmc2V0IC0gc3RhcnRPZmZzZXQpOwoJCQlwYXJzZXIucmVzZXQoc3ViU2V0VGV4dFN0b3JlUmVhZGVyLCBzdGFydE9mZnNldCk7CgkJfQoJCWVsc2UgewoJCQlTdHJpbmcgbmV3Tm9kZVRleHQgPSBnZXQoc3RhcnRPZmZzZXQsIGVuZE9mZnNldCAtIHN0YXJ0T2Zmc2V0KTsKCQkJcGFyc2VyLnJlc2V0KG5ld05vZGVUZXh0LCBzdGFydE9mZnNldCk7CgoJCX0KCgl9CgoJdm9pZCByZXNldFBhcnNlcihSZWFkZXIgcmVhZGVyLCBpbnQgc3RhcnRPZmZzZXQpIHsKCQlSZWdpb25QYXJzZXIgcGFyc2VyID0gZ2V0UGFyc2VyKCk7CgkJcGFyc2VyLnJlc2V0KHJlYWRlciwgc3RhcnRPZmZzZXQpOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb24jcmVzdW1lUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKQoJICovCglwdWJsaWMgdm9pZCByZXN1bWVQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpIHsKCQktLWZTdG9wcGVkQ291bnQ7CgkJaWYgKGZTdG9wcGVkQ291bnQgPT0gMCAmJiBmUmVlbnRyYW5jZUNvdW50ID09IDApCgkJCWV4ZWN1dGVQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlcygpOwoJfQoKCS8qKgoJICogQGRlcHJlY2F0ZWQgaW4gc3VwZXJjbGFzcyBpbiAzLjAgLSB1c2UgYSBGaW5kUmVwbGFjZURvY3VtZW50QWRhcHRlcgoJICogICAgICAgICAgICAgZGlyZWN0bHkKCSAqIEBzZWUgSURvY3VtZW50I3NlYXJjaAoJICovCglwdWJsaWMgaW50IHNlYXJjaChpbnQgc3RhcnRQb3NpdGlvbiwgU3RyaW5nIGZpbmRTdHJpbmcsIGJvb2xlYW4gZm9yd2FyZFNlYXJjaCwgYm9vbGVhbiBjYXNlU2Vuc2l0aXZlLCBib29sZWFuIHdob2xlV29yZCkgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQkvLyAoZG13KSBJIGFkZGVkIHRoaXMgd2FybmluZywgdG8ga25vdyBpZiBzdGlsbCBiZWluZyB1c2VkLiBJJ20gbm90CgkJLy8gc3VyZSBpdAoJCS8vIHdvcmtzIGFzIGV4cGVjdGVkIGFueSBsb25nZXIuCgkJLy8gYnV0IHRoZSB3YXJuaW5nIHNob3VsZCBiZSByZW1vdmVkLCBvbmNlIGtub3cuCgkJTG9nZ2VyLmxvZyhMb2dnZXIuSU5GTywgIldBUk5JTkc6IHVzaW5nIHVuc3VwcG9ydGVkIGRlcHJlY2F0ZWQgbWV0aG9kICdzZWFyY2gnIik7IC8vJE5PTi1OTFMtMSQKCQlpbnQgb2Zmc2V0ID0gLTE7CgkJSVJlZ2lvbiBtYXRjaCA9IG5ldyBGaW5kUmVwbGFjZURvY3VtZW50QWRhcHRlcih0aGlzKS5maW5kKHN0YXJ0UG9zaXRpb24sIGZpbmRTdHJpbmcsIGZvcndhcmRTZWFyY2gsIGNhc2VTZW5zaXRpdmUsIHdob2xlV29yZCwgZmFsc2UpOwoJCWlmIChtYXRjaCAhPSBudWxsKSB7CgkJCW9mZnNldCA9IG1hdGNoLmdldE9mZnNldCgpOwoJCX0KCQlyZXR1cm4gb2Zmc2V0OwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjc2V0VGV4dAoJICovCglwdWJsaWMgdm9pZCBzZXQoU3RyaW5nIHN0cmluZykgewoJCWlmIChEZWJ1Zy5kaXNwbGF5SW5mbykgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIk5vdGU6IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OnNldFRleHQoU3RyaW5nKSAuLi4uIGl0cyBiZXR0ZXIgdG8gdXNlIHNldFRleHQoc291cmNlLCBzdHJpbmcpIEFQSSBmb3Igc3RydWN0dXJlZERvY3VtZW50IHVwZGF0ZXMiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCQlzZXRUZXh0KG51bGwsIHN0cmluZyk7Cgl9CgoJLyoqCgkgKiBUaGlzIG1heSBiZSBtYXJrZWQgcHVibGljLCBidXQgc2hvdWxkIGJlIHBhY2thZ2VkIHByb3RlY3RlZCwgb25jZQoJICogcmVmYWN0b3JpbmcgaXMgY29tcGxldGUgKGluIG90aGVyIHdvcmRzLCBub3QgZm9yIGNsaWVudCB1c2UpLgoJICovCglwdWJsaWMgdm9pZCBzZXRDYWNoZWREb2N1bWVudFJlZ2lvbihJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHN0cnVjdHVyZWRSZWdpb24pIHsKCQlpZiAoVVNFX0xPQ0FMX1RIUkVBRCkgewoJCQlmQ3VycmVudERvY3VtbmV0UmVnaW9uQ2FjaGUuc2V0KHN0cnVjdHVyZWRSZWdpb24pOwoJCX0KCQllbHNlIHsKCQkJY2FjaGVkRG9jdW1lbnRSZWdpb24gPSBzdHJ1Y3R1cmVkUmVnaW9uOwoJCX0KCX0KCgkvKioKCSAqIFNldHMgdGhlIGRvY3VtZW50J3MgcGFydGl0aW9uZXIuCgkgKiAKCSAqIEBzZWUgSURvY3VtZW50UGFydGl0aW9uZXIKCSAqLwoJcHVibGljIHZvaWQgc2V0RG9jdW1lbnRQYXJ0aXRpb25lcihJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lcikgewoJCXNldERvY3VtZW50UGFydGl0aW9uZXIoSURvY3VtZW50RXh0ZW5zaW9uMy5ERUZBVUxUX1BBUlRJVElPTklORywgcGFydGl0aW9uZXIpOwoJfQoKCglwdWJsaWMgdm9pZCBzZXREb2N1bWVudFBhcnRpdGlvbmVyKFN0cmluZyBwYXJ0aXRpb25pbmcsIElEb2N1bWVudFBhcnRpdGlvbmVyIHBhcnRpdGlvbmVyKSB7CgkJaWYgKHBhcnRpdGlvbmVyID09IG51bGwpIHsKCQkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyAhPSBudWxsKSB7CgkJCQlmRG9jdW1lbnRQYXJ0aXRpb25lcnMucmVtb3ZlKHBhcnRpdGlvbmluZyk7CgkJCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzLnNpemUoKSA9PSAwKQoJCQkJCWZEb2N1bWVudFBhcnRpdGlvbmVycyA9IG51bGw7CgkJCX0KCQl9CgkJZWxzZSB7CgkJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgPT0gbnVsbCkKCQkJCWZEb2N1bWVudFBhcnRpdGlvbmVycyA9IG5ldyBIYXNoTWFwKCk7CgkJCWZEb2N1bWVudFBhcnRpdGlvbmVycy5wdXQocGFydGl0aW9uaW5nLCBwYXJ0aXRpb25lcik7CgkJfQoJCURvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZEV2ZW50IGV2ZW50ID0gbmV3IERvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZEV2ZW50KHRoaXMpOwoJCWV2ZW50LnNldFBhcnRpdGlvbkNoYW5nZShwYXJ0aXRpb25pbmcsIDAsIGdldExlbmd0aCgpKTsKCQlmaXJlRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkKGV2ZW50KTsKCX0KCglwdWJsaWMgdm9pZCBzZXRFbmNvZGluZ01lbWVudG8oRW5jb2RpbmdNZW1lbnRvIGVuY29kaW5nTWVtZW50bykgewoJCXRoaXMuZW5jb2RpbmdNZW1lbnRvID0gZW5jb2RpbmdNZW1lbnRvOwoJfQoKCXZvaWQgc2V0Rmlyc3REb2N1bWVudFJlZ2lvbihJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlZ2lvbikgewoJCWZpcnN0RG9jdW1lbnRSZWdpb24gPSByZWdpb247CgoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I3NldEluaXRpYWxMaW5lRGVsaW1pdGVyKGphdmEubGFuZy5TdHJpbmcpCgkgKi8KCXB1YmxpYyB2b2lkIHNldEluaXRpYWxMaW5lRGVsaW1pdGVyKFN0cmluZyBsaW5lRGVsaW1pdGVyKSB7CgkJLy8gbWFrZSBzdXJlIG91ciBwcmVmZXJyZWQgZGVsaW1pdGVyIGlzCgkJLy8gb25lIG9mIHRoZSBsZWdhbCBvbmVzCgkJaWYgKFV0aWxpdGllcy5jb250YWluc1N0cmluZyhnZXRMZWdhbExpbmVEZWxpbWl0ZXJzKCksIGxpbmVEZWxpbWl0ZXIpKSB7CgkJCWZJbml0aWFsTGluZURlbGltaXRlcj0gbGluZURlbGltaXRlcjsKCQl9CgkJZWxzZSB7CgkJCWlmIChMb2dnZXIuREVCVUdfRE9DVU1FTlQpCgkJCQlMb2dnZXIubG9nKExvZ2dlci5JTkZPLCAiQXR0ZW1wdCB0byBzZXQgbGluZWRlbGltaXRlciB0byBub24tbGVnYWwgZGVsaW1pdGVyIik7IC8vJE5PTi1OTFMtMSQgLy8kTk9OLU5MUy0yJAoJCQlmSW5pdGlhbExpbmVEZWxpbWl0ZXIgPSBQbGF0Zm9ybS5nZXRQcmVmZXJlbmNlc1NlcnZpY2UoKS5nZXRTdHJpbmcoUGxhdGZvcm0uUElfUlVOVElNRSwgUGxhdGZvcm0uUFJFRl9MSU5FX1NFUEFSQVRPUiwgU3lzdGVtLmdldFByb3BlcnR5KCJsaW5lLnNlcGFyYXRvciIpLCBuZXcgSVNjb3BlQ29udGV4dFtdIHsgbmV3IEluc3RhbmNlU2NvcGUoKSB9KTsvLyROT04tTkxTLTEkCgkJfQoJfQoKCXZvaWQgc2V0TGFzdERvY3VtZW50UmVnaW9uKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVnaW9uKSB7CgkJbGFzdERvY3VtZW50UmVnaW9uID0gcmVnaW9uOwoKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkRG9jdW1lbnQjc2V0TGluZURlbGltaXRlcihqYXZhLmxhbmcuU3RyaW5nKQoJICovCglwdWJsaWMgdm9pZCBzZXRMaW5lRGVsaW1pdGVyKFN0cmluZyBkZWxpbWl0ZXIpIHsKCQlzZXRJbml0aWFsTGluZURlbGltaXRlcihkZWxpbWl0ZXIpOwoJfQoKCS8qKgoJICogU2V0cyB0aGUgZG9jdW1lbnQncyBsaW5lIHRyYWNrZXIuIE11c3QgYmUgY2FsbGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YKCSAqIHRoZSBjb25zdHJ1Y3Rvci4KCSAqIAoJICogQHBhcmFtIHRyYWNrZXIKCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50J3MgbGluZSB0cmFja2VyCgkgKi8KCXByaXZhdGUgdm9pZCBzZXRMaW5lVHJhY2tlcihJTGluZVRyYWNrZXIgdHJhY2tlcikgewoJCWZUcmFja2VyID0gdHJhY2tlcjsKCX0KCglwdWJsaWMgdm9pZCBzZXRQYXJzZXIoUmVnaW9uUGFyc2VyIG5ld1BhcnNlcikgewoJCWludGVybmFsX3NldFBhcnNlcihuZXdQYXJzZXIpOwoJfQoKCS8qKgoJICogQHBhcmFtIHBvc2l0aW9uTWFuYWdlcgoJICogICAgICAgICAgICBUaGUgcG9zaXRpb25NYW5hZ2VyIHRvIHNldC4KCSAqLwoJLy8gVE9ETzogbWFrZSBwcml2YXRlIGlzIG5lZWRlZCwgZWxzZSByZW1vdmUKCXZvaWQgc2V0UG9zaXRpb25NYW5hZ2VyKEdlbmVyaWNQb3NpdGlvbk1hbmFnZXIgcG9zaXRpb25NYW5hZ2VyKSB7CgkJZlBvc2l0aW9uTWFuYWdlciA9IHBvc2l0aW9uTWFuYWdlcjsKCX0KCgkvKioKCSAqIAoJICovCglwdWJsaWMgdm9pZCBzZXRSZVBhcnNlcihJU3RydWN0dXJlZFRleHRSZVBhcnNlciBuZXdSZVBhcnNlcikgewoJCWZSZVBhcnNlciA9IG5ld1JlUGFyc2VyOwoJCWlmIChmUmVQYXJzZXIgIT0gbnVsbCkgewoJCQlmUmVQYXJzZXIuc2V0U3RydWN0dXJlZERvY3VtZW50KHRoaXMpOwoJCX0KCX0KCgkvKioKCSAqIE9uZSBvZiB0aGUgQVBJcyB0byBtYW5pcHVsYXRlIHRoZSBJU3RydWN0dXJlZERvY3VtZW50IGluIHRlcm1zIG9mIHRleHQuCgkgKi8KCXB1YmxpYyBTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCBzZXRUZXh0KE9iamVjdCByZXF1ZXN0ZXIsIFN0cmluZyB0aGVTdHJpbmcpIHsKCQlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCByZXN1bHQgPSBudWxsOwoKCQlyZXN1bHQgPSByZXBsYWNlVGV4dChyZXF1ZXN0ZXIsIDAsIGdldExlbmd0aCgpLCB0aGVTdHJpbmcsIHRydWUsIGdldE5leHRNb2RpZmljYXRpb25TdGFtcCgpKTsKCgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIFNldHMgdGhlIGRvY3VtZW50J3MgdGV4dCBzdG9yZS4gTXVzdCBiZSBjYWxsZWQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUKCSAqIGNvbnN0cnVjdG9yLgoJICogCgkgKiBAcGFyYW0gc3RvcmUKCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50J3MgdGV4dCBzdG9yZQoJICovCglwcml2YXRlIHZvaWQgc2V0VGV4dFN0b3JlKElUZXh0U3RvcmUgc3RvcmUpIHsKCQlmU3RvcmUgPSBzdG9yZTsKCX0KCglwdWJsaWMgdm9pZCBzZXRVbmRvTWFuYWdlcihJU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlciB1bmRvTWFuYWdlcikgewoKCQkvLyBpZiB0aGUgdW5kbyBtYW5hZ2VyIGhhcyBhbHJlYWR5IGJlZW4gc2V0LCB0aGVuCgkJLy8gZmFpbCBmYXN0LCBzaW5jZSBjaGFuZ2luZyB0aGUgdW5kbyBtYW5hZ2VyIHdpbGwgbGVhZAoJCS8vIHRvIHVudXN1YWwgcmVzdWx0cyAob3IgYXQgbGVhc3QgbG9zcyBvZiB1bmRvIHN0YWNrKS4KCQlpZiAoZlVuZG9NYW5hZ2VyICE9IG51bGwgJiYgZlVuZG9NYW5hZ2VyICE9IHVuZG9NYW5hZ2VyKSB7CgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oImNhbiBub3QgY2hhbmdlIHVuZG8gbWFuYWdlciBvbmNlIGl0cyBiZWVuIHNldCIpOyAvLyROT04tTkxTLTEkCgkJfQoJCWVsc2UgewoJCQlmVW5kb01hbmFnZXIgPSB1bmRvTWFuYWdlcjsKCQl9Cgl9CgoKCXB1YmxpYyB2b2lkIHN0YXJ0U2VxdWVudGlhbFJld3JpdGUoYm9vbGVhbiBub3JtYWxpemVkKSB7CgkJSVRleHRTdG9yZSBzdG9yZSA9IG5ldyBTZXF1ZW50aWFsUmV3cml0ZVRleHRTdG9yZShnZXRTdG9yZSgpKTsKCQlzZXRUZXh0U3RvcmUoc3RvcmUpOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb24jc3RvcFBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCkKCSAqLwoJcHVibGljIHZvaWQgc3RvcFBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCkgewoJCSsrZlN0b3BwZWRDb3VudDsKCX0KCgoJcHVibGljIHZvaWQgc3RvcFNlcXVlbnRpYWxSZXdyaXRlKCkgewoJCWlmIChnZXRTdG9yZSgpIGluc3RhbmNlb2YgU2VxdWVudGlhbFJld3JpdGVUZXh0U3RvcmUpIHsKCQkJU2VxdWVudGlhbFJld3JpdGVUZXh0U3RvcmUgc3J3cyA9IChTZXF1ZW50aWFsUmV3cml0ZVRleHRTdG9yZSkgZ2V0U3RvcmUoKTsKCQkJSVRleHRTdG9yZSBzb3VyY2UgPSBzcndzLmdldFNvdXJjZVN0b3JlKCk7CgkJCXNldFRleHRTdG9yZShzb3VyY2UpOwoJCQlzcndzLmRpc3Bvc2UoKTsKCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBqYXZhLmxhbmcuQ2hhclNlcXVlbmNlI3N1YlNlcXVlbmNlKGludCwgaW50KQoJICovCglwdWJsaWMgQ2hhclNlcXVlbmNlIHN1YlNlcXVlbmNlKGludCBhcmcwLCBpbnQgYXJnMSkgewoJCXJldHVybiBnZXQoYXJnMCwgYXJnMSk7Cgl9CgoJLyoqCgkgKiBAcGFyYW0gcmVzdWx0CgkgKi8KCXByaXZhdGUgdm9pZCB1cGRhdGVEZWxldGVkRmllbGRzKFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50IGV2ZW50KSB7CgkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbkxpc3Qgb2xkUmVnaW9ucyA9IGV2ZW50LmdldE9sZFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnMoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFJlZ2lvbnMuZ2V0TGVuZ3RoKCk7IGkrKykgewoJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiA9IG9sZFJlZ2lvbnMuaXRlbShpKTsKCQkJc3RydWN0dXJlZERvY3VtZW50UmVnaW9uLnNldERlbGV0ZWQodHJ1ZSk7CgkJfQoKCX0KCgkvKioKCSAqIENhbGxlZCBieSByZS1wYXJzZXIuIE5vdGU6IHRoaXMgbWV0aG9kIG1heSBiZSAicHVibGljIiBidXQgc2hvdWxkIG9ubHkKCSAqIGJlIGNhbGxlZCBieSByZS1wYXJzZXJzIGluIHRoZSByaWdodCBjaXJjdW1zdGFuY2VzLgoJICovCglwdWJsaWMgdm9pZCB1cGRhdGVEb2N1bWVudERhdGEoaW50IHN0YXJ0LCBpbnQgbGVuZ3RoVG9SZXBsYWNlLCBTdHJpbmcgY2hhbmdlcykgewoJCXN0b3BQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJCWdldFN0b3JlKCkucmVwbGFjZShzdGFydCwgbGVuZ3RoVG9SZXBsYWNlLCBjaGFuZ2VzKTsKCQl0cnkgewoJCQlnZXRUcmFja2VyKCkucmVwbGFjZShzdGFydCwgbGVuZ3RoVG9SZXBsYWNlLCBjaGFuZ2VzKTsKCQl9CgoJCWNhdGNoIChCYWRMb2NhdGlvbkV4Y2VwdGlvbiBlKSB7CgkJCS8vIHNob3VsZCBiZSBpbXBvc3NpYmxlIGhlcmUsIGJ1dCB3aWxsIGxvZyBmb3Igbm93CgkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZSk7CgkJfQoJCWlmIChmUG9zaXRpb25NYW5hZ2VyICE9IG51bGwpIHsKCQkJZlBvc2l0aW9uTWFuYWdlci51cGRhdGVQb3NpdGlvbnMobmV3IERvY3VtZW50RXZlbnQodGhpcywgc3RhcnQsIGxlbmd0aFRvUmVwbGFjZSwgY2hhbmdlcykpOwoJCX0KCQlmTW9kaWZpY2F0aW9uU3RhbXArKzsKCQlmTmV4dE1vZGlmaWNhdGlvblN0YW1wPSBNYXRoLm1heChmTW9kaWZpY2F0aW9uU3RhbXAsIGZOZXh0TW9kaWZpY2F0aW9uU3RhbXApOwoJCXJlc3VtZVBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCk7Cgl9CgoJcHJpdmF0ZSBTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCB1cGRhdGVNb2RlbChPYmplY3QgcmVxdWVzdGVyLCBpbnQgc3RhcnQsIGludCBsZW5ndGhUb1JlcGxhY2UsIFN0cmluZyBjaGFuZ2VzKSB7CgkJU3RydWN0dXJlZERvY3VtZW50RXZlbnQgcmVzdWx0ID0gbnVsbDsKCQlJU3RydWN0dXJlZFRleHRSZVBhcnNlciByZVBhcnNlciA9IGdldFJlUGFyc2VyKCk7CgkJLy8gaW5pdGlhbGl6ZSB0aGUgSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgd2l0aCB0aGUgc3RhbmRhcmQgZGF0YQoJCS8vIHRoYXQncwoJCS8vIGFsd2F5cyBuZWVkZWQKCQlyZVBhcnNlci5pbml0aWFsaXplKHJlcXVlc3Rlciwgc3RhcnQsIGxlbmd0aFRvUmVwbGFjZSwgY2hhbmdlcyk7CgkJcmVzdWx0ID0gcmVQYXJzZXIucmVwYXJzZSgpOwoJCS8vIGlmIHJlc3VsdCBpcyBudWxsIGF0IHRoaXMgcG9pbnQsIHRoZW4gdGhlcmUgbXVzdCBiZSBhbiBlcnJvciwgc2luY2UKCQkvLyBldmVuIGlmIHRoZXJlCgkJLy8gd2FzIG5vIGNoYW5nZSAoZWl0aGVyIGRpc2FsbG93IGR1ZSB0byByZWFkb25seSwgb3IgYSBwZXJzb24gcGFzdGVkCgkJLy8gdGhlIHNhbWUgdGhpbmcKCQkvLyB0aGV5IGhhZCBzZWxlY3RlZCkgdGhlbiBhICJOb0NoYW5nZSIgZXZlbnQgc2hvdWxkIGhhdmUgYmVlbiBmaXJlZC4KCQlBc3NlcnQuaXNOb3ROdWxsKHJlc3VsdCwgIm5vIHN0cnVjdHVyZWREb2N1bWVudCBldmVudCB3YXMgY3JlYXRlZCBpbiBJU3RydWN0dXJlZERvY3VtZW50Ojp1cGRhdGVTdHJ1Y3R1cmVkRG9jdW1lbnQiKTsgLy8kTk9OLU5MUy0xJAoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZG9jdW1lbnQuSUVuY29kZWREb2N1bWVudCNnZXRQcmVmZXJyZWRMaW5lRGVsaW1pdGVyKCkKCSAqLwoJcHVibGljIFN0cmluZyBnZXRQcmVmZXJyZWRMaW5lRGVsaW1pdGVyKCkgewoJCXJldHVybiBnZXREZWZhdWx0TGluZURlbGltaXRlcigpOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmRvY3VtZW50LklFbmNvZGVkRG9jdW1lbnQjc2V0UHJlZmVycmVkTGluZURlbGltaXRlcihqYXZhLmxhbmcuU3RyaW5nKQoJICovCglwdWJsaWMgdm9pZCBzZXRQcmVmZXJyZWRMaW5lRGVsaW1pdGVyKFN0cmluZyBwcm9iYWJsZUxpbmVEZWxpbWl0ZXIpIHsKCQlzZXRJbml0aWFsTGluZURlbGltaXRlcihwcm9iYWJsZUxpbmVEZWxpbWl0ZXIpOwoKCX0KCgoJLyoqCgkgKiBDbGFzcyB3aGljaCBpbXBsZW1lbnRzIHRoZSByZXdyaXRhYmxlIHNlc3Npb24gZm9yIHRoZSBTU0UuCgkgKiAKCSAqLwoJY2xhc3MgU3RydWN0dXJlZERvY3VtZW50UmV3cml0ZVNlc3Npb24gZXh0ZW5kcyBEb2N1bWVudFJld3JpdGVTZXNzaW9uIHsKCgkJLyoqCgkJICogQ3JlYXRlcyBhIG5ldyBzZXNzaW9uLgoJCSAqIAoJCSAqIEBwYXJhbSBzZXNzaW9uVHlwZQoJCSAqICAgICAgICAgICAgdGhlIHR5cGUgb2YgdGhpcyBzZXNzaW9uCgkJICovCgkJcHJvdGVjdGVkIFN0cnVjdHVyZWREb2N1bWVudFJld3JpdGVTZXNzaW9uKERvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlIHNlc3Npb25UeXBlKSB7CgkJCXN1cGVyKHNlc3Npb25UeXBlKTsKCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjc3RhcnRSZXdyaXRlU2Vzc2lvbihvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlKQoJICovCglwdWJsaWMgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBzdGFydFJld3JpdGVTZXNzaW9uKERvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlIHNlc3Npb25UeXBlKSB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uIHsKCQkvLyBkZWxlZ2F0ZSB0byBzdWItY2xhc3MsIHNvIFVJIHRocmVhZGluZyBpcyBoYW5kbGVkIGNvcnJlY3RseQoJCXJldHVybiBpbnRlcm5hbFN0YXJ0UmV3cml0ZVNlc3Npb24oc2Vzc2lvblR5cGUpOwoJfQoKCS8qKgoJICogTk9ULUFQSS4gRmluYWwgcHJvdGVjdGVkIHNvIGNsaWVudHMgbWF5IGNhbGwgdGhpcyBtZXRob2QgaWYgbmVlZGVkLCBidXQKCSAqIGNhbm5vdCBvdmVycmlkZS4KCSAqIAoJICogQHBhcmFtIHNlc3Npb25UeXBlCgkgKiBAcmV0dXJuCgkgKiBAdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbgoJICovCglmaW5hbCBwcm90ZWN0ZWQgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBpbnRlcm5hbFN0YXJ0UmV3cml0ZVNlc3Npb24oRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUgc2Vzc2lvblR5cGUpIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24gewoJCWlmIChnZXRBY3RpdmVSZXdyaXRlU2Vzc2lvbigpICE9IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oImFscmVhZHkgaW4gYSByZXdyaXRlIHNlc3Npb24iKTsKCgkJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBzZXNzaW9uID0gbmV3IFN0cnVjdHVyZWREb2N1bWVudFJld3JpdGVTZXNzaW9uKHNlc3Npb25UeXBlKTsKCQlEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQgZXZlbnQgPSBuZXcgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50KHRoaXMsIHNlc3Npb24sIERvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudC5TRVNTSU9OX1NUQVJUKTsKCQlmaXJlRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50KGV2ZW50KTsKCgkJSUxpbmVUcmFja2VyIHRyYWNrZXIgPSBnZXRUcmFja2VyKCk7CgkJaWYgKHRyYWNrZXIgaW5zdGFuY2VvZiBJTGluZVRyYWNrZXJFeHRlbnNpb24pIHsKCQkJSUxpbmVUcmFja2VyRXh0ZW5zaW9uIGV4dGVuc2lvbiA9IChJTGluZVRyYWNrZXJFeHRlbnNpb24pIHRyYWNrZXI7CgkJCWV4dGVuc2lvbi5zdGFydFJld3JpdGVTZXNzaW9uKHNlc3Npb24pOwoJCX0KCgkJc3RhcnRSZXdyaXRlU2Vzc2lvbk9uUGFydGl0aW9uZXJzKHNlc3Npb24pOwoKCQlpZiAoRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUuU0VRVUVOVElBTCA9PSBzZXNzaW9uVHlwZSkKCQkJc3RhcnRTZXF1ZW50aWFsUmV3cml0ZShmYWxzZSk7CgkJZWxzZSBpZiAoRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUuU1RSSUNUTFlfU0VRVUVOVElBTCA9PSBzZXNzaW9uVHlwZSkKCQkJc3RhcnRTZXF1ZW50aWFsUmV3cml0ZSh0cnVlKTsKCgkJZkFjdGl2ZVJld3JpdGVTZXNzaW9uID0gc2Vzc2lvbjsKCQlyZXR1cm4gc2Vzc2lvbjsKCX0KCgkvKioKCSAqIFN0YXJ0cyB0aGUgZ2l2ZW4gcmV3cml0ZSBzZXNzaW9uLgoJICoKCSAqIEBwYXJhbSBzZXNzaW9uIHRoZSByZXdyaXRlIHNlc3Npb24KCSAqIEBzaW5jZSAyLjAKCSAqLwoJZmluYWwgdm9pZCBzdGFydFJld3JpdGVTZXNzaW9uT25QYXJ0aXRpb25lcnMoRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBzZXNzaW9uKSB7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyAhPSBudWxsKSB7CgkJCUl0ZXJhdG9yIGU9IGZEb2N1bWVudFBhcnRpdGlvbmVycy52YWx1ZXMoKS5pdGVyYXRvcigpOwoJCQl3aGlsZSAoZS5oYXNOZXh0KCkpIHsKCQkJCU9iamVjdCBwYXJ0aXRpb25lcj0gZS5uZXh0KCk7CgkJCQlpZiAocGFydGl0aW9uZXIgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjMpIHsKCQkJCQlJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjMgZXh0ZW5zaW9uPSAoSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24zKSBwYXJ0aXRpb25lcjsKCQkJCQlleHRlbnNpb24uc3RhcnRSZXdyaXRlU2Vzc2lvbihzZXNzaW9uKTsKCQkJCX0KCQkJfQoJCX0KCX0KCgoJcHVibGljIHZvaWQgc3RvcFJld3JpdGVTZXNzaW9uKERvY3VtZW50UmV3cml0ZVNlc3Npb24gc2Vzc2lvbikgewoJCS8vIGRlbGVnYXRlIHRvIHN1Yi1jbGFzcywgc28gVUkgdGhyZWFkaW5nIGlzIGhhbmRsZWQgY29ycmVjdGx5CgkJaW50ZXJuYWxTdG9wUmV3cml0ZVNlc3Npb24oc2Vzc2lvbik7Cgl9CgoJLyoqCgkgKiBOT1QtQVBJLiBGaW5hbCBwcm90ZWN0ZWQgc28gY2xpZW50cyBtYXkgY2FsbCB0aGlzIG1ldGhvZCBpZiBuZWVkZWQsIGJ1dAoJICogY2Fubm90IG92ZXJyaWRlLgoJICogCgkgKiBAcGFyYW0gc2Vzc2lvbgoJICovCglmaW5hbCBwcm90ZWN0ZWQgdm9pZCBpbnRlcm5hbFN0b3BSZXdyaXRlU2Vzc2lvbihEb2N1bWVudFJld3JpdGVTZXNzaW9uIHNlc3Npb24pIHsKCQlpZiAoZkFjdGl2ZVJld3JpdGVTZXNzaW9uID09IHNlc3Npb24pIHsKCQkJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUgc2Vzc2lvblR5cGUgPSBzZXNzaW9uLmdldFNlc3Npb25UeXBlKCk7CgkJCWlmIChEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZS5TRVFVRU5USUFMID09IHNlc3Npb25UeXBlIHx8IERvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlLlNUUklDVExZX1NFUVVFTlRJQUwgPT0gc2Vzc2lvblR5cGUpCgkJCQlzdG9wU2VxdWVudGlhbFJld3JpdGUoKTsKCgkJCXN0b3BSZXdyaXRlU2Vzc2lvbk9uUGFydGl0aW9uZXJzKHNlc3Npb24pOwoKCQkJSUxpbmVUcmFja2VyIHRyYWNrZXIgPSBnZXRUcmFja2VyKCk7CgkJCWlmICh0cmFja2VyIGluc3RhbmNlb2YgSUxpbmVUcmFja2VyRXh0ZW5zaW9uKSB7CgkJCQlJTGluZVRyYWNrZXJFeHRlbnNpb24gZXh0ZW5zaW9uID0gKElMaW5lVHJhY2tlckV4dGVuc2lvbikgdHJhY2tlcjsKCQkJCWV4dGVuc2lvbi5zdG9wUmV3cml0ZVNlc3Npb24oc2Vzc2lvbiwgZ2V0KCkpOwoJCQl9CgoJCQlEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQgZXZlbnQgPSBuZXcgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50KHRoaXMsIHNlc3Npb24sIERvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudC5TRVNTSU9OX1NUT1ApOwoJCQlmaXJlRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50KGV2ZW50KTsKCQkJZkFjdGl2ZVJld3JpdGVTZXNzaW9uID0gbnVsbDsKCQl9Cgl9CgoJLyoqCgkgKiBTdG9wcyB0aGUgZ2l2ZW4gcmV3cml0ZSBzZXNzaW9uLgoJICoKCSAqIEBwYXJhbSBzZXNzaW9uIHRoZSByZXdyaXRlIHNlc3Npb24KCSAqIEBzaW5jZSAyLjAKCSAqLwoJZmluYWwgdm9pZCBzdG9wUmV3cml0ZVNlc3Npb25PblBhcnRpdGlvbmVycyhEb2N1bWVudFJld3JpdGVTZXNzaW9uIHNlc3Npb24pIHsKCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzICE9IG51bGwpIHsKCQkJRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkRXZlbnQgZXZlbnQ9IG5ldyBEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWRFdmVudCh0aGlzKTsKCQkJSXRlcmF0b3IgZT0gZkRvY3VtZW50UGFydGl0aW9uZXJzLmtleVNldCgpLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChlLmhhc05leHQoKSkgewoJCQkJU3RyaW5nIHBhcnRpdGlvbmluZz0gKFN0cmluZykgZS5uZXh0KCk7CgkJCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lcj0gKElEb2N1bWVudFBhcnRpdGlvbmVyKSBmRG9jdW1lbnRQYXJ0aXRpb25lcnMuZ2V0KHBhcnRpdGlvbmluZyk7CgkJCQlpZiAocGFydGl0aW9uZXIgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjMpIHsKCQkJCQlJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjMgZXh0ZW5zaW9uPSAoSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24zKSBwYXJ0aXRpb25lcjsKCQkJCQlleHRlbnNpb24uc3RvcFJld3JpdGVTZXNzaW9uKHNlc3Npb24pOwoJCQkJCWV2ZW50LnNldFBhcnRpdGlvbkNoYW5nZShwYXJ0aXRpb25pbmcsIDAsIGdldExlbmd0aCgpKTsKCQkJCX0KCQkJfQoJCQlpZiAoIWV2ZW50LmlzRW1wdHkoKSkKCQkJCWZpcmVEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWQoZXZlbnQpOwoJCX0KCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNnZXRBY3RpdmVSZXdyaXRlU2Vzc2lvbigpCgkgKi8KCXB1YmxpYyBEb2N1bWVudFJld3JpdGVTZXNzaW9uIGdldEFjdGl2ZVJld3JpdGVTZXNzaW9uKCkgewoJCXJldHVybiBmQWN0aXZlUmV3cml0ZVNlc3Npb247Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjYWRkRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgYWRkRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKElEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoJCQlBc3NlcnQuaXNOb3ROdWxsKGxpc3RlbmVyKTsKCQkJaWYgKGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzID09IG51bGwpIHsKCQkJCWZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzID0gbmV3IEFycmF5TGlzdCgxKTsKCQkJfQoJCQlpZiAoIWZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzLmNvbnRhaW5zKGxpc3RlbmVyKSkKCQkJCWZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzLmFkZChsaXN0ZW5lcik7CgkJfQoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I3JlbW92ZURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcihvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIpCgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcihJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCUFzc2VydC5pc05vdE51bGwobGlzdGVuZXIpOwoJCQlpZiAoZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMgIT0gbnVsbCkKCQkJCWZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzLnJlbW92ZShsaXN0ZW5lcik7CgkJfQoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I3JlcGxhY2UoaW50LCBpbnQsCgkgKiAgICAgIGphdmEubGFuZy5TdHJpbmcsIGxvbmcpCgkgKi8KCXB1YmxpYyB2b2lkIHJlcGxhY2UoaW50IG9mZnNldCwgaW50IGxlbmd0aCwgU3RyaW5nIHRleHQsIGxvbmcgbW9kaWZpY2F0aW9uU3RhbXApIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmVwbGFjZVRleHQodGhpcywgb2Zmc2V0LCBsZW5ndGgsIHRleHQsIGZhbHNlLCBtb2RpZmljYXRpb25TdGFtcCk7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjc2V0KGphdmEubGFuZy5TdHJpbmcsCgkgKiAgICAgIGxvbmcpCgkgKi8KCXB1YmxpYyB2b2lkIHNldChTdHJpbmcgdGV4dCwgbG9uZyBtb2RpZmljYXRpb25TdGFtcCkgewoJCS8vIGJ1ZyAxNTEwNjkgLSBvdmVyd3JpdGUgcmVhZCBvbmx5IHJlZ2lvbnMgd2hlbiBzZXR0aW5nIGVudGlyZSBkb2N1bWVudAoJCSByZXBsYWNlVGV4dChudWxsLCAwLCBnZXRMZW5ndGgoKSwgdGV4dCwgdHJ1ZSwgbW9kaWZpY2F0aW9uU3RhbXApOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I2dldE1vZGlmaWNhdGlvblN0YW1wKCkKCSAqLwoJcHVibGljIGxvbmcgZ2V0TW9kaWZpY2F0aW9uU3RhbXAoKSB7CgkJcmV0dXJuIGZNb2RpZmljYXRpb25TdGFtcDsKCX0KCQoJcHJpdmF0ZSBsb25nIGdldE5leHRNb2RpZmljYXRpb25TdGFtcCgpIHsKCQlpZiAoZk5leHRNb2RpZmljYXRpb25TdGFtcCA9PSBMb25nLk1BWF9WQUxVRSB8fCBmTmV4dE1vZGlmaWNhdGlvblN0YW1wID09IElEb2N1bWVudEV4dGVuc2lvbjQuVU5LTk9XTl9NT0RJRklDQVRJT05fU1RBTVApCgkJCWZOZXh0TW9kaWZpY2F0aW9uU3RhbXA9IDA7CgkJZWxzZQoJCQlmTmV4dE1vZGlmaWNhdGlvblN0YW1wPSBmTmV4dE1vZGlmaWNhdGlvblN0YW1wICsgMTsKCgkJcmV0dXJuIGZOZXh0TW9kaWZpY2F0aW9uU3RhbXA7Cgl9CgoJLyoqCgkgKiBGaXJlcyBhbiBldmVudCwgYXMgc3BlY2lmaWVkLCB0byB0aGUgYXNzb2NpYXRlZCBsaXN0ZW5lcnMuCgkgKiAKCSAqIEBwYXJhbSBldmVudAoJICogICAgICAgICAgICBUaGUgZXZlbnQgdG8gZmlyZSwgZWl0aGVyIGEgc3RhcnQgb3Igc3RvcCBldmVudC4KCSAqLwoJcHJpdmF0ZSB2b2lkIGZpcmVEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQoRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50IGV2ZW50KSB7CgkJaWYgKGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzID09IG51bGwgfHwgZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMuc2l6ZSgpID09IDApCgkJCXJldHVybjsKCgkJTGlzdCBsaXN0ID0gbmV3IEFycmF5TGlzdChmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycyk7CgkJSXRlcmF0b3IgZSA9IGxpc3QuaXRlcmF0b3IoKTsKCQl3aGlsZSAoZS5oYXNOZXh0KCkpIHsKCQkJSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lciBsID0gKElEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIpIGUubmV4dCgpOwoJCQlsLmRvY3VtZW50UmV3cml0ZVNlc3Npb25DaGFuZ2VkKGV2ZW50KTsKCQl9Cgl9Cn0K