LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAxLCAyMDA2IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gaW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqICAgICBKZW5zIEx1a293c2tpL0lubm9vcHJhY3QgLSBpbml0aWFsIHJlbmFtaW5nL3Jlc3RydWN0dXJpbmcKICogICAgIEplc3BlciBTdGVlbiBN+GxsZXIgLSBpbml0aWFsIElEb2N1bWVudEV4dGVuc2lvbjQgc3VwcG9ydCAtICMxMDI4MjIKICogICAgIAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwudGV4dDsKCmltcG9ydCBqYXZhLmlvLlJlYWRlcjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuUGxhdGZvcm07CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRQYXJ0aXRpb25pbmdFeGNlcHRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRlZmF1bHRMaW5lVHJhY2tlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuRG9jdW1lbnRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UmV3cml0ZVNlc3Npb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGU7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkZpbmRSZXBsYWNlRG9jdW1lbnRBZGFwdGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uMzsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNDsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50TGlzdGVuZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uMjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSUxpbmVUcmFja2VyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JTGluZVRyYWNrZXJFeHRlbnNpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklQb3NpdGlvblVwZGF0ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklSZWdpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklUZXh0U3RvcmU7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklUeXBlZFJlZ2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuUG9zaXRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LlNlcXVlbnRpYWxSZXdyaXRlVGV4dFN0b3JlOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5UeXBlZFJlZ2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5Mb2dnZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwuZG9jdW1lbnQuU3RydWN0dXJlZERvY3VtZW50RmFjdG9yeTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5lbmNvZGluZy5FbmNvZGluZ01lbWVudG87CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwubHRrLnBhcnNlci5SZWdpb25QYXJzZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLkFib3V0VG9CZUNoYW5nZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuSU1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmV2ZW50cy5JU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLk5vQ2hhbmdlRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLlJlZ2lvbkNoYW5nZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuUmVnaW9uc1JlcGxhY2VkRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLlN0cnVjdHVyZWREb2N1bWVudEV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmV2ZW50cy5TdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkRG9jdW1lbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZERvY3VtZW50UmVnaW9uOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLnRleHQuSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbkxpc3Q7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZFBhcnRpdGlvbmluZzsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkVGV4dFJlUGFyc2VyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnRleHQucnVsZXMuU3RydWN0dXJlZFRleHRQYXJ0aXRpb25lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51bmRvLklTdHJ1Y3R1cmVkVGV4dFVuZG9NYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnVuZG8uU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51dGlsLkFzc2VydDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC51dGlsLkRlYnVnOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnV0aWwuVXRpbGl0aWVzOwoKCi8qKgogKiBUaGUgc3RhbmRhcmQgaW1wbGVtZW50YXRpb24gb2Ygc3RydWN0dXJlZCBkb2N1bWVudC4KICovCnB1YmxpYyBjbGFzcyBCYXNpY1N0cnVjdHVyZWREb2N1bWVudCBpbXBsZW1lbnRzIElTdHJ1Y3R1cmVkRG9jdW1lbnQsIElEb2N1bWVudEV4dGVuc2lvbiwgSURvY3VtZW50RXh0ZW5zaW9uMywgSURvY3VtZW50RXh0ZW5zaW9uNCwgQ2hhclNlcXVlbmNlLCBJUmVnaW9uQ29tcGFyaWJsZSB7CgoJLyoqCgkgKiBUaGlzIFRocmVhZExvY2FsIGNvbnN0cnVjdCBpcyB1c2VkIHNvIGVhY2ggdGhyZWFkIGNhbiBtYWludGFpbiBpdHMgb25seQoJICogcG9pbnRlciB0byB0aGUgZG91YmxlIGxpbmtlZCBsaXN0IHRoYXQgbWFuYWdlcyB0aGUgZG9jdW1lbnRzIHJlZ2lvbnMuCgkgKiBUaGUgb25seSB0aGluZyB3ZSAiZ2F1cmQiIGZvciBpcyB0aGF0IGEgcHJldmlvdXNseSBjYWNoZWQgcmVnaW9uIGhhcwoJICogYmVlbiBkZWxldGVkLgoJICogCgkgKiBUaGUgb2JqZWN0IHRoYXQgaXMga2VwdCBpbiB0aGUgdGhyZWFkIGxvY2FsJ3MgbWFwLCBpcyBqdXN0IGEgcG9pbnRlciB0bwoJICogYW4gYXJyYXkgcG9zaXRpb24uIFRoYXQncyBiZWNhdXNlIHRoZSBvYmplY3QgdGhlcmUgbmVlZHMgdG8gYmUgImZyZWUiCgkgKiBmcm9tIHJlZmVyZW5jZXMgdG8gb3RoZXIgb2JqZWN0cywgb3IgaXQgd2lsbCBub3QgYmUgZ2FyYmFnZSBjb2xsZWN0ZWQuCgkgKi8KCXByaXZhdGUgY2xhc3MgQ3VycmVudERvY3VtZW50UmVnaW9uQ2FjaGUgewoJCS8vIEknbSBhc3N1bWluZyBmb3Igbm93IHRoZXJlIHdvdWxkIG5ldmVyIGJlIHNvIG1hbnkgdGhyZWFkcyB0aGF0CgkJLy8gdGhpcyBhcnJheUxpc3QgbmVlZHMgdG8gYmUgYm91bmRlZCwgb3IgJ2NsZWFuZWQgdXAnLgoJCS8vIHRoaXMgYXNzdW1wdGlvbiBzaG91bGQgYmUgdGVzdGVkIGluIHByYWN0aWNlIGFuZCBsb25nIHJ1bm5pbmcKCQkvLyBqb2JzIC0tIGZvdW5kIG5vdCB0byBiZSBhIGdvb2QgYXNzdW1wdGlvbi4gU2VlIGJlbG93LgoJCXByaXZhdGUgTGlzdCBjYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5ID0gQ29sbGVjdGlvbnMuc3luY2hyb25pemVkTGlzdChuZXcgQXJyYXlMaXN0KCkpOwoJCXByaXZhdGUgZmluYWwgYm9vbGVhbiBERUJVRyA9IGZhbHNlOwoJCXByaXZhdGUgZmluYWwgaW50IE1BWF9TSVpFID0gNTA7CgoKCQlwcml2YXRlIFRocmVhZExvY2FsIHRocmVhZExvY2FsQ2FjaGVQb3NpdGlvbiA9IG5ldyBUaHJlYWRMb2NhbCgpOwoKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGdldCgpIHsKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24gPSBudWxsOwoJCQlpbnQgcG9zID0gZ2V0VGhyZWFkTG9jYWxQb3NpdGlvbigpOwoJCQl0cnkgewoJCQkJcmVnaW9uID0gKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24pIGNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuZ2V0KHBvcyk7CgkJCX0KCQkJY2F0Y2ggKEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gZSkgewoJCQkJLy8gZXZlbiB0aG91Z2ggdGhlIGNhY2hlZFJlZ2lvblBvc2l0aW9uIGlzIHN5bmNocm9uaXplZCwKCQkJCS8vIHRoYXQganVzdCBtZWFucyBlYWNoIGFjY2VzcyBpcyBzeW5jcm9uaXplZCwgaXRzCgkJCQkvLyBzdGlsbCBwb3NzaWJsZSBmb3IgYW5vdGhlciB0aHJlYWQgdG8gY2F1c2UgaXQgdG8KCQkJCS8vIGJlIGNsZWFyZWQsIGFmdGVyIHRoaXMgdGhyZWFkIGdldHMgaXQgcG9zaXRpb24uCgkJCQkvLyBTbywgaWYgdGhhdCBoYXBwZW5zLCBhbGwgd2UgY2FuIGRvIGlzIHJlc2V0IHRvIGJlZ2lubmluZy4KCQkJCS8vIFRoaXMgc2hvdWxkIGJlIGV4dHJlbWVseSByYXJlIChpbiBvdGhlciB3b3JkcywgcHJvYmFibHkKCQkJCS8vIG5vdCB3b3J0aCB1c2luZyBzeW5jaHJvbml6ZWQgYmxvY2tzCgkJCQkvLyB0byBhY2Nlc3MgY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS4KCQkJCXJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJCXJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCQlpZiAocmVnaW9uID09IG51bGwpIHsKCQkJCXJlZ2lvbiA9IHJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCQllbHNlCgkJCS8vIHJlZ2lvbiBub3QgbnVsbAoJCQlpZiAocmVnaW9uLmlzRGVsZXRlZCgpKSB7CgkJCQlyZWdpb24gPSByZXNldFRvSW5pdGlhbFN0YXRlKCk7CgkJCX0KCQkJcmV0dXJuIHJlZ2lvbjsKCQl9CgoJCXByaXZhdGUgaW50IGdldFRocmVhZExvY2FsUG9zaXRpb24oKSB7CgkJCU9iamVjdCB0aHJlYWRMb2NhbE9iamVjdCA9IHRocmVhZExvY2FsQ2FjaGVQb3NpdGlvbi5nZXQoKTsKCQkJaW50IHBvcyA9IC0xOwoJCQlpZiAodGhyZWFkTG9jYWxPYmplY3QgPT0gbnVsbCkgewoKCQkJCXBvcyA9IHJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJfQoJCQllbHNlIHsKCQkJCXBvcyA9ICgoSW50ZWdlcikgdGhyZWFkTG9jYWxPYmplY3QpLmludFZhbHVlKCk7CgkJCX0KCQkJcmV0dXJuIHBvczsKCQl9CgoJCS8qKgoJCSAqIEByZXR1cm4KCQkgKi8KCQlwcml2YXRlIGludCByZWluaXRUaHJlYWRMb2NhbFBvc2l0aW9uKCkgewoJCQlJbnRlZ2VyIHBvc2l0aW9uOwoJCQlpbnQgcG9zOwoJCQkvLyBUT0RPX2Z1dHVyZTogdGhpbmsgb2YgYSBiZXR0ZXIgc29sdXRpb24gdGhhdCBkb2Vzbid0CgkJCS8vIHJlcXVpcmUgdGhpcyBrbHVkZ2UuIFRoaXMgaXMgZXNwZWNpYWxseSByZXF1aXJlZCBiZWNhdXNlCgkJCS8vIHNvbWUgaW5mcmFzdHVyZSwgc3VjaCBhcyByZWNvbmNpbGVyLCBhY3R1YWxseSBudWxsIG91dAoJCQkvLyB0aGVpciB0aHJlYWQgb2JqZWN0IGFuZCByZWNyZWF0ZSBpdCwgNTAwIG1zZWNzIGxhdGVyCgkJCS8vIChhcHByb3hpbWF0ZWx5KS4KCQkJLy8gTm90ZTogdGhlIGxpa2VseSBzb2x1dGlvbiBpbiBmdXR1cmUgaXMgdG8gY2xlYXIgYWZ0ZXIgZXZlcnkKCQkJLy8gaGVhdnkgdXNlIG9mIGdldENhY2hlZFJlZ2lvbiwgc3VjaCBhcyBpbiBjcmVhdGluZyBub2RlCgkJCS8vIGxpc3RzLCBvciByZXBhcnNpbmcgb3IgcGFydGlvbmluZy4KCQkJaWYgKGNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuc2l6ZSgpID4gTUFYX1NJWkUpIHsKCQkJCWNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuY2xlYXIoKTsKCQkJCWlmIChERUJVRykgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheSBjbGVhcmVkIGF0IHNpemUgIiArIE1BWF9TSVpFKTsgLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJCXBvc2l0aW9uID0gbmV3IEludGVnZXIoY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5zaXplKCkpOwoJCQl0aHJlYWRMb2NhbENhY2hlUG9zaXRpb24uc2V0KHBvc2l0aW9uKTsKCQkJY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5hZGQocG9zaXRpb24uaW50VmFsdWUoKSwgbnVsbCk7CgkJCXBvcyA9IHBvc2l0aW9uLmludFZhbHVlKCk7CgkJCXJldHVybiBwb3M7CgkJfQoKCQlwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVzZXRUb0luaXRpYWxTdGF0ZSgpIHsKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb247CgkJCXJlZ2lvbiA9IGdldEZpcnN0U3RydWN0dXJlZERvY3VtZW50UmVnaW9uKCk7CgkJCXNldChyZWdpb24pOwoJCQlyZXR1cm4gcmVnaW9uOwoJCX0KCgkJLy8gVE9ETzogbWFrZSBwcml2aXRlIGlmIHVzZWQsIGVsc2UgZGVsZXRlCgkJdm9pZCBzZXQoaW50IHBvcywgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24pIHsKCQkJY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5zZXQocG9zLCByZWdpb24pOwoJCX0KCgkJdm9pZCBzZXQoSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24pIHsKCQkJdHJ5IHsKCQkJCWludCBwb3MgPSBnZXRUaHJlYWRMb2NhbFBvc2l0aW9uKCk7CgkJCQljYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5LnNldChwb3MsIHJlZ2lvbik7CgkJCX0KCQkJY2F0Y2ggKEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gZSkgewoJCQkJLy8gZXZlbiB0aG91Z2ggdGhlIGNhY2hlZFJlZ2lvblBvc2l0aW9uIGlzIHN5bmNocm9uaXplZCwKCQkJCS8vIHRoYXQganVzdCBtZWFucyBlYWNoIGFjY2VzcyBpcyBzeW5jcm9uaXplZCwgaXRzCgkJCQkvLyBzdGlsbCBwb3NzaWJsZSBmb3IgYW5vdGhlciB0aHJlYWQgdG8gY2F1c2UgaXQgdG8KCQkJCS8vIGJlIGNsZWFyZWQsIGFmdGVyIHRoaXMgdGhyZWFkIGdldHMgaXQgcG9zaXRpb24uCgkJCQkvLyBTbywgaWYgdGhhdCBoYXBwZW5zLCBhbGwgd2UgY2FuIGRvIGlzIHJlc2V0IHRvIGJlZ2lubmluZy4KCQkJCS8vIFRoaXMgc2hvdWxkIGJlIGV4dHJlbWVseSByYXJlIChpbiBvdGhlciB3b3JkcywgcHJvYmFibHkKCQkJCS8vIG5vdCB3b3J0aCB1c2luZyBzeW5jaHJvbml6ZWQgYmxvY2tzCgkJCQkvLyB0byBhY2Nlc3MgY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS4KCQkJCXJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJCXJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCX0KCX0KCgkvKioKCSAqIFRoaXMgTnVsbERvY3VtZW50RXZlbnQgaXMgdXNlZCB0byBjb21wbGV0ZSB0aGUgImFib3V0VG9DaGFuZ2UiIGFuZAoJICogImNoYW5nZWQiIGN5Y2xlLCB3aGVuIGluIGZhY3QgdGhlIG9yaWdpbmFsIGNoYW5nZSBpcyBubyBsb25nZXIgdmFsaWQuCgkgKiBUaGUgb25seSBrbm93biAodmFsaWQpIGNhc2Ugb2YgdGhpcyBpcyB3aGVuIGEgbW9kZWwgcmUtaW5pdGlhbGl6ZSB0YWtlcwoJICogcGxhY2UsIHdoaWNoIGNhdXNlcyBzZXRUZXh0IHRvIGJlIGNhbGxlZCBpbiB0aGUgbWlkZGxlIG9mIHNvbWUgcHJldmlvdXMKCSAqIGNoYW5nZS4gW1RoaXMgYXJjaGl0ZWN0dXJlIHdpbGwgYmUgaW1wcm92ZWQgaW4gZnV0dXJlXS4KCSAqLwoJcHVibGljIGNsYXNzIE51bGxEb2N1bWVudEV2ZW50IGV4dGVuZHMgRG9jdW1lbnRFdmVudCB7CgkJcHVibGljIE51bGxEb2N1bWVudEV2ZW50KCkgewoJCQl0aGlzKEJhc2ljU3RydWN0dXJlZERvY3VtZW50LnRoaXMsIDAsIDAsICIiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJcHJpdmF0ZSBOdWxsRG9jdW1lbnRFdmVudChJRG9jdW1lbnQgZG9jLCBpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoLCBTdHJpbmcgdGV4dCkgewoJCQlzdXBlcihkb2MsIG9mZnNldCwgbGVuZ3RoLCB0ZXh0KTsKCQl9Cgl9CgoJY2xhc3MgUmVnaXN0ZXJlZFJlcGxhY2UgewoJCS8qKiBUaGUgb3duZXIgb2YgdGhpcyByZXBsYWNlIG9wZXJhdGlvbi4gKi8KCQlJRG9jdW1lbnRMaXN0ZW5lciBmT3duZXI7CgkJLyoqIFRoZSByZXBsYWNlIG9wZXJhdGlvbiAqLwoJCUlEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSBmUmVwbGFjZTsKCgkJLyoqCgkJICogQ3JlYXRlcyBhIG5ldyBidW5kbGUgb2JqZWN0LgoJCSAqIAoJCSAqIEBwYXJhbSBvd25lcgoJCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50IGxpc3RlbmVyIG93bmluZyB0aGUgcmVwbGFjZSBvcGVyYXRpb24KCQkgKiBAcGFyYW0gcmVwbGFjZQoJCSAqICAgICAgICAgICAgdGhlIHJlcGxhY2Ugb3BlcmF0aW9uCgkJICovCgkJUmVnaXN0ZXJlZFJlcGxhY2UoSURvY3VtZW50TGlzdGVuZXIgb3duZXIsIElEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSByZXBsYWNlKSB7CgkJCWZPd25lciA9IG93bmVyOwoJCQlmUmVwbGFjZSA9IHJlcGxhY2U7CgkJfQoJfQoKCS8qKgoJICogdGhlc2UgY29udHJvbCB2YXJpYWJsZSBpc24ndCBtYXJrIGFzICdmaW5hbCcgc2luY2UgdGhlcmUncyBzb21lIHVuaXQKCSAqIHRlc3RzIHRoYXQgbWFuaXB1bGF0ZSBpdC4gRm9yIGZpbmFsIHByb2R1Y3QsIGl0IHNob3VsZCBiZS4KCSAqLwoKCXByaXZhdGUgc3RhdGljIGJvb2xlYW4gVVNFX0xPQ0FMX1RIUkVBRCA9IHRydWU7CgoJLyoqCgkgKiBwdXJlbHkgZm9yIGRlYnVnZ2luZy9wZXJmb3JtYW5jZSBtZWFzdXJlbWVudHMgSW4gcHJhY3RpY2UsIHdvdWxkIGFsd2F5cwoJICogYmUgJ3RydWUnLiAoYW5kIHNob3VsZCBuZXZlciBiZSBjYWxsZWQgYnkgY2FsbGVkIGJ5IGNsaWVudHMpLiBJdHMgbm90CgkgKiAnZmluYWwnIG9yIHByaXZhdGUganVzdCBzbyBpdCBjYW4gYmUgdmFyaWVkIGR1cmluZwoJICogZGVidWdnaW5nL3BlcmZvcm1hbmNlIG1lYXN1cmVtZW50IHJ1bnMuCgkgKiAKCSAqIEBwYXJhbSB1c2VfbG9jYWxfdGhyZWFkCgkgKi8KCXB1YmxpYyBzdGF0aWMgdm9pZCBzZXRVU0VfTE9DQUxfVEhSRUFEKGZpbmFsIGJvb2xlYW4gdXNlX2xvY2FsX3RocmVhZCkgewoJCVVTRV9MT0NBTF9USFJFQUQgPSB1c2VfbG9jYWxfdGhyZWFkOwoJfQoKCXByaXZhdGUgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBjYWNoZWREb2N1bWVudFJlZ2lvbjsKCXByaXZhdGUgRW5jb2RpbmdNZW1lbnRvIGVuY29kaW5nTWVtZW50bzsKCXByaXZhdGUgYm9vbGVhbiBmQWNjZXB0UG9zdE5vdGlmaWNhdGlvblJlcGxhY2VzID0gdHJ1ZTsKCXByaXZhdGUgQ3VycmVudERvY3VtZW50UmVnaW9uQ2FjaGUgZkN1cnJlbnREb2N1bW5ldFJlZ2lvbkNhY2hlOwoJcHJpdmF0ZSBEb2N1bWVudEV2ZW50IGZEb2N1bWVudEV2ZW50OwoJcHJpdmF0ZSBJRG9jdW1lbnRMaXN0ZW5lcltdIGZEb2N1bWVudExpc3RlbmVyczsKCgkvKioKCSAqIFRoZSByZWdpc3RlcmVkIGRvY3VtZW50IHBhcnRpdGlvbmVycy4KCSAqLwoJcHJpdmF0ZSBNYXAgZkRvY3VtZW50UGFydGl0aW9uZXJzOwoJLyoqIFRoZSByZWdpc3RlcmVkIGRvY3VtZW50IHBhcnRpdGlvbmluZyBsaXN0ZW5lcnMgKi8KCXByaXZhdGUgTGlzdCBmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnM7Cglwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZmlyc3REb2N1bWVudFJlZ2lvbjsKCXByaXZhdGUgUmVnaW9uUGFyc2VyIGZQYXJzZXI7Cglwcml2YXRlIEdlbmVyaWNQb3NpdGlvbk1hbmFnZXIgZlBvc2l0aW9uTWFuYWdlcjsKCXByaXZhdGUgTGlzdCBmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXM7Cglwcml2YXRlIElEb2N1bWVudExpc3RlbmVyW10gZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnM7Cglwcml2YXRlIGludCBmUmVlbnRyYW5jZUNvdW50ID0gMDsKCXByaXZhdGUgSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgZlJlUGFyc2VyOwoJcHJpdmF0ZSBpbnQgZlN0b3BwZWRDb3VudCA9IDA7CgoJcHJpdmF0ZSBJVGV4dFN0b3JlIGZTdG9yZTsKCXByaXZhdGUgT2JqZWN0W10gZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnM7Cglwcml2YXRlIE9iamVjdFtdIGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzOwoJcHJpdmF0ZSBPYmplY3RbXSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnM7CgoJcHJpdmF0ZSBMaXN0IGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzOwoKCXByaXZhdGUgSUxpbmVUcmFja2VyIGZUcmFja2VyOwoJcHJpdmF0ZSBJU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlciBmVW5kb01hbmFnZXI7Cglwcml2YXRlIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gbGFzdERvY3VtZW50UmVnaW9uOwoKCXByaXZhdGUgYnl0ZVtdIGxpc3RlbmVyTG9jayA9IG5ldyBieXRlWzBdOwoJcHJpdmF0ZSBOdWxsRG9jdW1lbnRFdmVudCBOVUxMX0RPQ1VNRU5UX0VWRU5UOwoKCS8vCgkvKioKCSAqIGluIGNhc2UgcHJlZmVycmVkIGRlbGltaXRlciBpcyBub3Qgc2V0LCB3ZSdsbCBhc3N1bWUgdGhlIHBsYXRmb3JtCgkgKiBkZWZhdWx0IE5vdGU6IGl0IGlzIG5vdCBmaW5hbCBzdGF0aWMgdG8gbWFrZSBzdXJlIGl0IHdvbid0IGJlIGlubGluZWQKCSAqIGJ5IGNvbXBpbGVyLgoJICovCglwcml2YXRlIGZpbmFsIFN0cmluZyBQbGF0Zm9ybUxpbmVEZWxpbWl0ZXIgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoImxpbmUuc2VwYXJhdG9yIik7IC8vJE5PTi1OTFMtMSQKCS8qKgoJICogdGhlb3JldGljYWxseSwgYSBkb2N1bWVudCBjYW4gY29udGFpbiBtaXhlZCBsaW5lIGRlbGltaXRlcnMKCSAqLwoJcHJpdmF0ZSBTdHJpbmcgcHJlZmVyZWREZWxpbWl0ZXI7Cglwcml2YXRlIGZpbmFsIFN0cmluZyBSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSA9ICJfUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUllfIjsgLy8kTk9OLU5MUy0xJAoJLyoqCgkgKiBDdXJyZW50IHJld3JpdGUgc2Vzc2lvbiwgb3Igbm9uZSBpZiBub3QgcHJlc2VudGx5IHJld3JpdGluZy4KCSAqLwoJcHJpdmF0ZSBEb2N1bWVudFJld3JpdGVTZXNzaW9uIGZBY3RpdmVSZXdyaXRlU2Vzc2lvbjsKCS8qKgoJICogTGFzdCBtb2RpZmljYXRpb24gc3RhbXAsIGF1dG9tYXRpY2FsbHkgdXBkYXRlZCBvbiBjaGFuZ2UuCgkgKi8KCXByaXZhdGUgbG9uZyBmTW9kaWZpY2F0aW9uU3RhbXA7CgkvKioKCSAqIGRlYnVnIHZhcmlhYmxlIG9ubHkKCSAqIAoJICogQHBhcmFtIHBhcnNlcgoJICovCglwcml2YXRlIGxvbmcgc3RhcnRTdHJlYW1UaW1lOwoJLyoqCgkgKiBkZWJ1ZyB2YXJpYWJsZSBvbmx5CgkgKiAKCSAqIEBwYXJhbSBwYXJzZXIKCSAqLwoJcHJpdmF0ZSBsb25nIHN0YXJ0VGltZTsKCglwdWJsaWMgQmFzaWNTdHJ1Y3R1cmVkRG9jdW1lbnQoKSB7CgkJc3VwZXIoKTsKCQlmQ3VycmVudERvY3VtbmV0UmVnaW9uQ2FjaGUgPSBuZXcgQ3VycmVudERvY3VtZW50UmVnaW9uQ2FjaGUoKTsKCQlmU3RvcmUgPSBuZXcgU3RydWN0dXJlZERvY3VtZW50VGV4dFN0b3JlKDUwLCAzMDApOwoJCXNldExpbmVUcmFja2VyKG5ldyBEZWZhdWx0TGluZVRyYWNrZXIoKSk7CgkJTlVMTF9ET0NVTUVOVF9FVkVOVCA9IG5ldyBOdWxsRG9jdW1lbnRFdmVudCgpOwoKCQlpbnRlcm5hbF9hZGRQb3NpdGlvbkNhdGVnb3J5KFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZKTsKCQlpbnRlcm5hbF9hZGRQb3NpdGlvblVwZGF0ZXIobmV3IERlbGV0ZUVxdWFsUG9zaXRpb25VcGRhdGVyKFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZKSk7CgoJfQoKCS8qKgoJICogVGhpcyBpcyB0aGUgcHJpbWFyeSB3YXkgdG8gZ2V0IGEgbmV3IHN0cnVjdHVyZWREb2N1bWVudC4gSXRzIGJlc3QgdG8KCSAqIHVzZSB0aGUgZmFjdG9yeSBtZXRob2RzIGluIE1vZGVsTWFuZ2VyIHRvIGNyZWF0ZSBhIG5ldwoJICogSVN0cnVjdHVyZWREb2N1bWVudCwgc2luY2UgaXQgd2lsbCBnZXQgYW5kIGluaXRpYWxpemUgdGhlIHBhcnNlcgoJICogYWNjb3JkaW5nIHRvIHRoZSBkZXNpcmVkIGNvbnRlbnQgdHlwZS4KCSAqLwoJcHVibGljIEJhc2ljU3RydWN0dXJlZERvY3VtZW50KFJlZ2lvblBhcnNlciBwYXJzZXIpIHsKCQl0aGlzKCk7CgkJQXNzZXJ0LmlzTm90TnVsbChwYXJzZXIsICJQcm9ncmFtIEVycm9yOiBJU3RydWN0dXJlZERvY3VtZW50IGNhbiBub3QgYmUgY3JlYXRlZCB3aXRoIG51bGwgcGFyc2VyIik7IC8vJE5PTi1OTFMtMSQKCQkvLyBnbyB0aHJvdWdoIHNldHRlciBpbiBjYXNlIHRoZXJlIGlzIHNpZGUgZWZmZWN0cwoJCWludGVybmFsX3NldFBhcnNlcihwYXJzZXIpOwoJfQoKCXByaXZhdGUgdm9pZCBfY2xlYXJEb2N1bWVudEV2ZW50KCkgewoJCS8vIG5vIGhhcmQgYW5kIGZhc3QgcmVxdWlyZW1lbnQgdG8gbnVsbCBvdXQgLi4uIGp1c3Qgc2VlbXMgbGlrZQoJCS8vIGEgZ29vZCBpZGVhLCBzaW5jZSB3ZSBhcmUgZG9uZSB3aXRoIGl0LgoJCWZEb2N1bWVudEV2ZW50ID0gbnVsbDsKCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2UoT2JqZWN0W10gbGlzdGVuZXJzKSB7CgkJLy8gbW9zdCBEb2N1bWVudEFib3V0VG9CZUNoYW5nZWQgbGlzdGVuZXJzIGRvIG5vdCBhbnRpY2lwYXRlCgkJLy8gRG9jdW1lbnRFdmVudCA9PSBudWxsLiBTbyBtYWtlIHN1cmUgZG9jdW1lbnRFdmVudCBpcyBub3QKCQkvLyBudWxsLiAodGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLCB5ZXQgaXQgZG9lcyBzb21ldGltZXMpCgkJaWYgKGZEb2N1bWVudEV2ZW50ID09IG51bGwpIHsKCQkJZkRvY3VtZW50RXZlbnQgPSBuZXcgTnVsbERvY3VtZW50RXZlbnQoKTsKCQl9CgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCS8vIE5vdGU6IHRoZSBkb2NFdmVudCBpcyBjcmVhdGVkIGluIHJlcGxhY2VUZXh0IEFQSQoJCQkvLyBmaXJlCgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkoKElEb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5kb2N1bWVudEFib3V0VG9CZUNoYW5nZWQoZkRvY3VtZW50RXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgbm90aWZ5RG9jdW1lbnRQYXJ0aXRpb25lcnNBYm91dFRvQ2hhbmdlKERvY3VtZW50RXZlbnQgZG9jdW1lbnRFdmVudCkgewoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgIT0gbnVsbCkgewoJCQlJdGVyYXRvciBlID0gZkRvY3VtZW50UGFydGl0aW9uZXJzLnZhbHVlcygpLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChlLmhhc05leHQoKSkgewoJCQkJSURvY3VtZW50UGFydGl0aW9uZXIgcCA9IChJRG9jdW1lbnRQYXJ0aXRpb25lcikgZS5uZXh0KCk7CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCXAuZG9jdW1lbnRBYm91dFRvQmVDaGFuZ2VkKGRvY3VtZW50RXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIF9maXJlRG9jdW1lbnRDaGFuZ2VkKE9iamVjdFtdIGxpc3RlbmVycywgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgZXZlbnQpIHsKCgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCS8vIE5PVEU6IGRvY3VtZW50IGV2ZW50IGlzIGNyZWF0ZWQgaW4gcmVwbGFjZSBUZXh0IEFQSSBhbmQgc2V0VGV4dAoJCQkvLyBBUEkKCQkJLy8gbm93IGZpcmUKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBob2xkTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlzdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCX0KCgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkvLyBOb3RlczogZkRvY3VtZW50RXZlbnQgY2FuIGJlICJzdWRkZW5seSIgbnVsbCwgaWYgb25lIG9mCgkJCQkJLy8gdGhlCgkJCQkJLy8gcHJldmlvdXMgY2hhbmdlcwoJCQkJCS8vIGNhdXNlZCBhICJzZXRUZXh0IiB0byBiZSBjYWxsZWQuIFRoZSBvbmx5IGtub3duIGNhc2Ugb2YKCQkJCQkvLyB0aGlzCgkJCQkJLy8gaXMgYSBtb2RlbCByZXNldAoJCQkJCS8vIGR1ZSB0byBwYWdlIGRpcmVjdGl2ZSBjaGFuZ2luZy4gRXZlbnR1YWxseSB3ZSBzaG91bGQKCQkJCQkvLyBjaGFuZ2UKCQkJCQkvLyBhcmNoZXRlY3R1cmUgdG8gaGF2ZQoJCQkJCS8vIGV2ZW50IHF1ZSBhbmQgYmUgYWJsZSB0byAiY2FuY2VsIiBwZW5kaW5nIGV2ZW50cywgYnV0CgkJCQkJLy8gZm9yCgkJCQkJLy8gbm93LCB3ZSdsbCBqdXN0IHBhc3MgYQoJCQkJCS8vIE51bGxEb2N1bWVudEV2ZW50LiBCeSB0aGUgd2F5LCBpdCBpcyBpbXBvcnRhbnQgdG8gc2VuZAoJCQkJCS8vIHNvbWV0aGluZywgc2luY2UgY2xpZW50cyBtaWdodAoJCQkJCS8vIGhhdmUgaW5kZXRlcm1pbmFudCBzdGF0ZSBkdWUgdG8gImFib3V0VG9DaGFuZ2UiIGJlaW5nCgkJCQkJLy8gc2VudAoJCQkJCS8vIGVhcmxpZXIuCgkJCQkJaWYgKGZEb2N1bWVudEV2ZW50ID09IG51bGwpIHsKCQkJCQkJKChJRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkuZG9jdW1lbnRDaGFuZ2VkKE5VTExfRE9DVU1FTlRfRVZFTlQpOwoJCQkJCX0KCQkJCQllbHNlIHsKCQkJCQkJKChJRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkuZG9jdW1lbnRDaGFuZ2VkKGZEb2N1bWVudEV2ZW50KTsKCQkJCQl9CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCWxvbmcgc3RvcFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgSVN0cnVjdHVyZWREb2N1bWVudDo6ZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50LiBUaW1lIHdhcyAiICsgKHN0b3BUaW1lIC0gc3RhcnRUaW1lKSArICIgbXNlY3MgdG8gZmlyZSBOZXdNb2RlbEV2ZW50IHRvIGluc3RhbmNlIG9mICIgKyBob2xkTGlzdGVuZXJzW2ldLmdldENsYXNzKCkpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0RvY3VtZW50Q2hhbmdlZChEb2N1bWVudEV2ZW50IGRvY3VtZW50RXZlbnQpIHsKCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzICE9IG51bGwpIHsKCQkJSXRlcmF0b3IgZSA9IGZEb2N1bWVudFBhcnRpdGlvbmVycy52YWx1ZXMoKS5pdGVyYXRvcigpOwoJCQl3aGlsZSAoZS5oYXNOZXh0KCkpIHsKCQkJCUlEb2N1bWVudFBhcnRpdGlvbmVyIHAgPSAoSURvY3VtZW50UGFydGl0aW9uZXIpIGUubmV4dCgpOwoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQlpZiAocCBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uKSB7CgkJCQkJCS8vIElSZWdpb24gY2hhbmdlZFBhcnRpb24gPQoJCQkJCQkoKElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uKSBwKS5kb2N1bWVudENoYW5nZWQyKGRvY3VtZW50RXZlbnQpOwoJCQkJCX0KCQkJCQllbHNlIHsKCQkJCQkJcC5kb2N1bWVudENoYW5nZWQoZG9jdW1lbnRFdmVudCk7CgkJCQkJfQoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCX0KCQl9Cgl9CgoKCXByaXZhdGUgdm9pZCBfZmlyZUV2ZW50KE9iamVjdFtdIGxpc3RlbmVycywgTm9DaGFuZ2VFdmVudCBldmVudCkgewoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJKChJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLm5vQ2hhbmdlKGV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIF9maXJlRXZlbnQoT2JqZWN0W10gbGlzdGVuZXJzLCBSZWdpb25DaGFuZ2VkRXZlbnQgZXZlbnQpIHsKCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBob2xkTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlzdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCX0KCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCSgoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5yZWdpb25DaGFuZ2VkKGV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIF9maXJlRXZlbnQoT2JqZWN0W10gbGlzdGVuZXJzLCBSZWdpb25zUmVwbGFjZWRFdmVudCBldmVudCkgewoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJKChJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLnJlZ2lvbnNSZXBsYWNlZChldmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCWxvbmcgc3RvcFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgSVN0cnVjdHVyZWREb2N1bWVudDo6ZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50LiBUaW1lIHdhcyAiICsgKHN0b3BUaW1lIC0gc3RhcnRUaW1lKSArICIgbXNlY3MgdG8gZmlyZSBOZXdNb2RlbEV2ZW50IHRvIGluc3RhbmNlIG9mICIgKyBob2xkTGlzdGVuZXJzW2ldLmdldENsYXNzKCkpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBfZmlyZUV2ZW50KE9iamVjdFtdIGxpc3RlbmVycywgU3RydWN0dXJlZERvY3VtZW50UmVnaW9uc1JlcGxhY2VkRXZlbnQgZXZlbnQpIHsKCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBob2xkTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlzdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCX0KCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCSgoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5ub2Rlc1JlcGxhY2VkKGV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIF9maXJlU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZShPYmplY3RbXSBsaXN0ZW5lcnMpIHsKCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJLy8gTm90ZTogdGhlIGRvY0V2ZW50IGlzIGNyZWF0ZWQgaW4gcmVwbGFjZVRleHQgQVBJCgkJCS8vIGZpcmUKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBob2xkTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlzdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCX0KCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gbm90aWNlIHRoZSBBYm91dFRvQmVDaGFuZ2VkRXZlbnQgaXMgY3JlYXRlZCBmcm9tIHRoZQoJCQkJCS8vIERvY3VtZW50RXZlbnQsIHNpbmNlIGl0IGlzIChuZWFybHkpCgkJCQkJLy8gdGhlIHNhbWUgaW5mb3JtYXRpb24uID9XaGF0IHRvIGRvIGFib3V0CgkJCQkJLy8gb3JpZ2luYWxSZXF1ZXN0ZXI/CgkJCQkJaWYgKGZEb2N1bWVudEV2ZW50ID09IG51bGwpIHsKCQkJCQkJZkRvY3VtZW50RXZlbnQgPSBuZXcgTnVsbERvY3VtZW50RXZlbnQoKTsKCQkJCQl9CgkJCQkJQWJvdXRUb0JlQ2hhbmdlZEV2ZW50IGFib3V0VG9CZUNoYW5nZWRFdmVudCA9IG5ldyBBYm91dFRvQmVDaGFuZ2VkRXZlbnQodGhpcywgbnVsbCwgZkRvY3VtZW50RXZlbnQuZ2V0VGV4dCgpLCBmRG9jdW1lbnRFdmVudC5nZXRPZmZzZXQoKSwgZkRvY3VtZW50RXZlbnQuZ2V0TGVuZ3RoKCkpOwoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkoKElNb2RlbEFib3V0VG9CZUNoYW5nZWRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkubW9kZWxBYm91dFRvQmVDaGFuZ2VkKGFib3V0VG9CZUNoYW5nZWRFdmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCWxvbmcgc3RvcFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgSVN0cnVjdHVyZWREb2N1bWVudDo6ZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50LiBUaW1lIHdhcyAiICsgKHN0b3BUaW1lIC0gc3RhcnRUaW1lKSArICIgbXNlY3MgdG8gZmlyZSBOZXdNb2RlbEV2ZW50IHRvIGluc3RhbmNlIG9mICIgKyBob2xkTGlzdGVuZXJzW2ldLmdldENsYXNzKCkpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJfQoJfQoKCXByb3RlY3RlZCB2b2lkIGFjcXVpcmVMb2NrKCkgewoJCS8vIGRvIG5vdGhpbmcgaGVyZSBpbiBzdXBlciBjbGFzcwoJfQoKCS8qKgoJICogYWRkTW9kZWxBYm91dFRvQmVDaGFuZ2VkTGlzdGVuZXIgbWV0aG9kIGNvbW1lbnQuCgkgKi8KCXB1YmxpYyB2b2lkIGFkZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVyKElNb2RlbEFib3V0VG9CZUNoYW5nZWRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQkvLyBtYWtlIHN1cmUgbGlzdGVuZXIgaXMgbm90IGFscmVhZHkgaW4gbGlzdGVuaW5nCgkJCS8vIChhbmQgaWYgaXQgaXMsIHByaW50IGEgd2FybmluZyB0byBhaWQgZGVidWdnaW5nLCBpZiBuZWVkZWQpCgkJCWlmICghVXRpbGl0aWVzLmNvbnRhaW5zKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCWludCBvbGRTaXplID0gMDsKCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJLy8gbm9ybWFsbHkgd29uJ3QgYmUgbnVsbCwgYnV0IHdlIG5lZWQgdG8gYmUgc3VyZSwgZm9yCgkJCQkJLy8gZmlyc3QKCQkJCQkvLyB0aW1lIHRocm91Z2gKCQkJCQlvbGRTaXplID0gZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJfQoJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplICsgMTsKCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCVN5c3RlbS5hcnJheWNvcHkoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMsIDAsIG5ld0xpc3RlbmVycywgMCwgb2xkU2l6ZSk7CgkJCQl9CgkJCQkvLyBhZGQgbGlzdGVuZXIgdG8gbGFzdCBwb3NpdGlvbgoJCQkJbmV3TGlzdGVuZXJzW25ld1NpemUgLSAxXSA9IGxpc3RlbmVyOwoJCQkJLy8KCQkJCS8vIG5vdyBzd2l0Y2ggbmV3IGZvciBvbGQKCQkJCWZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJLy8KCQkJfQoJCX0KCX0KCgkvKioKCSAqIFRoZSBTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0bmVycyBhbmQgTW9kZWxDaGFnbmVkTGlzdGVuZXJzIGFyZSB2ZXJ5CgkgKiBzaW1pbGFyLiBUaGV5IGJvdGggcmVjZWl2ZSBpZGVudGljYWwgZXZlbnRzLiBUaGUgZGlmZmVyZW5jZSBpcyB0aGUKCSAqIHRpbWluZy4gVGhlICJwdXJlIiBTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0bmVycyBhcmUgbm90aWZpZWQgYWZ0ZXIgdGhlCgkgKiBzdHJ1Y3R1cmVkRG9jdW1lbnQgaGFzIGJlZW4gY2hhbmdlZCwgYnV0IGJlZm9yZSBvdGhlciwgcmVsYXRlZCBtb2RlbHMKCSAqIG1heSBoYXZlIGJlZW4gY2hhbmdlZCBzdWNoIGFzIHRoZSBTdHJ1Y3R1cmFsIE1vZGVsLiBUaGUgU3RydWN0dXJhbAoJICogbW9kZWwgaXMgaW4gZmFjdCBpdHNlbGYgYSAicHVyZSIgU3RydWN0dXJlZERvY3VtZW50TGlzdG5lci4gVGhlCgkgKiBNb2RlbENoYW5nZWRMaXN0ZW5lcnMgY2FuIHJlc3QgYXNzdXJlZCB0aGF0IGFsbCBtb2RlbHMgYW5kIGRhdGEgaGF2ZQoJICogYmVlbiB1cGRhdGVkIGZyb20gdGhlIGNoYW5nZSBieSB0aGUgdGllbSB0aGV5IGFyZSBub3RpZmllZC4gVGhpcyBpcwoJICogZXNwZWNpYWxseSBpbXBvcnRhbnQgZm9yIHRoZSB0ZXh0IHdpZGdldCwgZm9yIGV4YW1wbGUsIHdoaWNoIG1heSByZWx5CgkgKiBvbiBib3RoIHN0cnVjdHVyZWREb2N1bWVudCBhbmQgc3RydWN0dXJhbCBtb2RlbCBpbmZvcm1hdGlvbi4KCSAqLwoJcHVibGljIHZvaWQgYWRkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXIoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkgewoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJJU3RydWN0dXJlZERvY3VtZW50OjphZGRNb2RlbENoYW5nZWRMaXN0ZW5lci4gUmVxdWVzdCB0byBhZGQgYW4gaW5zdGFuY2Ugb2YgIiArIGxpc3RlbmVyLmdldENsYXNzKCkgKyAiIGFzIGEgbGlzdGVuZXIgb24gc3RydWN0dXJlZERvY3VtZW50LiIpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQl9CgkJCS8vIG1ha2Ugc3VyZSBsaXN0ZW5lciBpcyBub3QgYWxyZWFkeSBpbiBsaXN0ZW5pbmcKCQkJLy8gKGFuZCBpZiBpdCBpcywgcHJpbnQgYSB3YXJuaW5nIHRvIGFpZCBkZWJ1Z2dpbmcsIGlmIG5lZWRlZCkKCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQlpZiAoRGVidWcuZGlzcGxheVdhcm5pbmdzKSB7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJJU3RydWN0dXJlZERvY3VtZW50OjphZGRNb2RlbENoYW5nZWRMaXN0ZW5lci4gbGlzdGVuZXIgIiArIGxpc3RlbmVyICsgIiB3YXMgYWRkZWRlZCBtb3JlIHRoYW4gb25jZS4gIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQkJZWxzZSB7CgkJCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpIHsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZE1vZGVsQ2hhbmdlZExpc3RlbmVyLiBBZGRpbmcgYW4gaW5zdGFuY2Ugb2YgIiArIGxpc3RlbmVyLmdldENsYXNzKCkgKyAiIGFzIGEgbGlzdGVuZXIgb24gc3RydWN0dXJlZERvY3VtZW50LiIpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQkJaW50IG9sZFNpemUgPSAwOwoJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQkvLyBub3JtYWxseSB3b24ndCBiZSBudWxsLCBidXQgd2UgbmVlZCB0byBiZSBzdXJlLCBmb3IKCQkJCQkvLyBmaXJzdAoJCQkJCS8vIHRpbWUgdGhyb3VnaAoJCQkJCW9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycy5sZW5ndGg7CgkJCQl9CgkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgKyAxOwoJCQkJT2JqZWN0W10gbmV3TGlzdGVuZXJzID0gbmV3IE9iamVjdFtuZXdTaXplXTsKCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJU3lzdGVtLmFycmF5Y29weShmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgMCwgbmV3TGlzdGVuZXJzLCAwLCBvbGRTaXplKTsKCQkJCX0KCQkJCS8vIGFkZCBsaXN0ZW5lciB0byBsYXN0IHBvc2l0aW9uCgkJCQluZXdMaXN0ZW5lcnNbbmV3U2l6ZSAtIDFdID0gbGlzdGVuZXI7CgkJCQkvLwoJCQkJLy8gbm93IHN3aXRjaCBuZXcgZm9yIG9sZAoJCQkJZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQkvLwoJCQkJLy8gd2hlbiBhIGxpc3RlbmVyIGlzIGFkZGVkLAoJCQkJLy8gc2VuZCB0aGUgbmV3IG1vZGVsIGV2ZW50IHRvIHRoYXQgb25lIHBhcnRpY3VsYXIgbGlzdGVuZXIsCgkJCQkvLyBzbyBpdAoJCQkJLy8gY2FuIGluaXRpYWxpemUgaXRzZWxmIHdpdGggdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIG1vZGVsCgkJCQkvLyBsaXN0ZW5lci5uZXdNb2RlbChuZXcgTmV3TW9kZWxFdmVudCh0aGlzLCBsaXN0ZW5lcikpOwoJCQl9CgkJfQoJfQoKCXB1YmxpYyB2b2lkIGFkZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcihJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKERlYnVnLmRlYnVnU3RydWN0dXJlZERvY3VtZW50KSB7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZFN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyLiBSZXF1ZXN0IHRvIGFkZCBhbiBpbnN0YW5jZSBvZiAiICsgbGlzdGVuZXIuZ2V0Q2xhc3MoKSArICIgYXMgYSBsaXN0ZW5lciBvbiBzdHJ1Y3R1cmVkRG9jdW1lbnQuIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCX0KCQkJLy8gbWFrZSBzdXJlIGxpc3RlbmVyIGlzIG5vdCBhbHJlYWR5IGluIGxpc3RlbmluZwoJCQkvLyAoYW5kIGlmIGl0IGlzLCBwcmludCBhIHdhcm5pbmcgdG8gYWlkIGRlYnVnZ2luZywgaWYgbmVlZGVkKQoJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQlpZiAoRGVidWcuZGlzcGxheVdhcm5pbmdzKSB7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJJU3RydWN0dXJlZERvY3VtZW50OjphZGRTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lci4gbGlzdGVuZXIgIiArIGxpc3RlbmVyICsgIiB3YXMgYWRkZWRlZCBtb3JlIHRoYW4gb25jZS4gIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQkJZWxzZSB7CgkJCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpIHsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZFN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyLiBBZGRpbmcgYW4gaW5zdGFuY2Ugb2YgIiArIGxpc3RlbmVyLmdldENsYXNzKCkgKyAiIGFzIGEgbGlzdGVuZXIgb24gc3RydWN0dXJlZERvY3VtZW50LiIpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQkJaW50IG9sZFNpemUgPSAwOwoJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJLy8gbm9ybWFsbHkgd29uJ3QgYmUgbnVsbCwgYnV0IHdlIG5lZWQgdG8gYmUgc3VyZSwgZm9yCgkJCQkJLy8gZmlyc3QKCQkJCQkvLyB0aW1lIHRocm91Z2gKCQkJCQlvbGRTaXplID0gZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLmxlbmd0aDsKCQkJCX0KCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSArIDE7CgkJCQlPYmplY3RbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgT2JqZWN0W25ld1NpemVdOwoJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJU3lzdGVtLmFycmF5Y29weShmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIDAsIG5ld0xpc3RlbmVycywgMCwgb2xkU2l6ZSk7CgkJCQl9CgkJCQkvLyBhZGQgbGlzdGVuZXIgdG8gbGFzdCBwb3NpdGlvbgoJCQkJbmV3TGlzdGVuZXJzW25ld1NpemUgLSAxXSA9IGxpc3RlbmVyOwoJCQkJLy8KCQkJCS8vIG5vdyBzd2l0Y2ggbmV3IGZvciBvbGQKCQkJCWZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJCS8vCgkJCQkvLyB3aGVuIGEgbGlzdGVuZXIgaXMgYWRkZWQsCgkJCQkvLyBzZW5kIHRoZSBuZXcgbW9kZWwgZXZlbnQgdG8gdGhhdCBvbmUgcGFydGljdWxhciBsaXN0ZW5lciwKCQkJCS8vIHNvIGl0CgkJCQkvLyBjYW4gaW5pdGlhbGl6ZSBpdHNlbGYgd2l0aCB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgbW9kZWwKCQkJCS8vIGxpc3RlbmVyLm5ld01vZGVsKG5ldyBOZXdNb2RlbEV2ZW50KHRoaXMsIGxpc3RlbmVyKSk7CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBXZSBtYW5hZ2Ugb3VyIG93biBkb2N1bWVudCBsaXN0bmVycywgaW5zdGVhZCBvZiBkZWxlZ2F0aW5nIHRvIG91cgoJICogcGFyZW50RG9jdW1lbnQsIHNvIHdlIGNhbiBmaXJlIGF0IHZlcnkgZW5kIChhbmQgbm90IHdoZW4gdGhlCgkgKiBwYXJlbnREb2N1bWVudCBjaGFuZ2VzKS4KCSAqIAoJICovCglwdWJsaWMgdm9pZCBhZGREb2N1bWVudExpc3RlbmVyKElEb2N1bWVudExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCS8vIG1ha2Ugc3VyZSBsaXN0ZW5lciBpcyBub3QgYWxyZWFkeSBpbiBsaXN0ZW5pbmcKCQkJLy8gKGFuZCBpZiBpdCBpcywgcHJpbnQgYSB3YXJuaW5nIHRvIGFpZCBkZWJ1Z2dpbmcsIGlmIG5lZWRlZCkKCQkJaWYgKCFVdGlsaXRpZXMuY29udGFpbnMoZkRvY3VtZW50TGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCWludCBvbGRTaXplID0gMDsKCQkJCWlmIChmRG9jdW1lbnRMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCS8vIG5vcm1hbGx5IHdvbid0IGJlIG51bGwsIGJ1dCB3ZSBuZWVkIHRvIGJlIHN1cmUsIGZvcgoJCQkJCS8vIGZpcnN0CgkJCQkJLy8gdGltZSB0aHJvdWdoCgkJCQkJb2xkU2l6ZSA9IGZEb2N1bWVudExpc3RlbmVycy5sZW5ndGg7CgkJCQl9CgkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgKyAxOwoJCQkJSURvY3VtZW50TGlzdGVuZXJbXSBuZXdMaXN0ZW5lcnMgPSBudWxsOwoJCQkJbmV3TGlzdGVuZXJzID0gbmV3IElEb2N1bWVudExpc3RlbmVyW25ld1NpemVdOwoJCQkJaWYgKGZEb2N1bWVudExpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJU3lzdGVtLmFycmF5Y29weShmRG9jdW1lbnRMaXN0ZW5lcnMsIDAsIG5ld0xpc3RlbmVycywgMCwgb2xkU2l6ZSk7CgkJCQl9CgkJCQkvLyBhZGQgbGlzdGVuZXIgdG8gbGFzdCBwb3NpdGlvbgoJCQkJbmV3TGlzdGVuZXJzW25ld1NpemUgLSAxXSA9IGxpc3RlbmVyOwoJCQkJLy8gbm93IHN3aXRjaCBuZXcgZm9yIG9sZAoJCQkJZkRvY3VtZW50TGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQl9CgkJfQoJfQoKCS8qCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50I2FkZERvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIob3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcikKCSAqIAoJICogUmVnaXN0ZXJzIHRoZSBkb2N1bWVudCBwYXJ0aXRpb25pbmcgbGlzdGVuZXIgd2l0aCB0aGUgZG9jdW1lbnQuIEFmdGVyCgkgKiByZWdpc3RyYXRpb24gdGhlIElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyIGlzIGluZm9ybWVkIGFib3V0IGVhY2gKCSAqIHBhcnRpdGlvbiBjaGFuZ2UgY2F1c2UgYnkgYSBkb2N1bWVudCBtYW5pcHVsYXRpb24uIElmIGEgZG9jdW1lbnQKCSAqIHBhcnRpdGlvbmluZyBsaXN0ZW5lciBpcyBhbHNvIGEgZG9jdW1lbnQgbGlzdGVuZXIsIHRoZSBmb2xsb3dpbmcKCSAqIG5vdGlmaWNhdGlvbiBzZXF1ZW5jZSBpcyBndWFyYW50ZWVkIGlmIGEgZG9jdW1lbnQgbWFuaXB1bGF0aW9uIGNoYW5nZXMKCSAqIHRoZSBkb2N1bWVudCBwYXJ0aXRpb25pbmc6IDEpCgkgKiBsaXN0ZW5lci5kb2N1bWVudEFib3V0VG9CZUNoYW5nZWQoRG9jdW1lbnRFdmVudCk7IDIpCgkgKiBsaXN0ZW5lci5kb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWQoKTsgMykKCSAqIGxpc3RlbmVyLmRvY3VtZW50Q2hhbmdlZChEb2N1bWVudEV2ZW50KTsgSWYgdGhlIGxpc3RlbmVyIGlzIGFscmVhZHkKCSAqIHJlZ2lzdGVyZWQgbm90aGluZyBoYXBwZW5zLgoJICogCgkgKiBAc2VlIElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyCgkgKi8KCglwdWJsaWMgdm9pZCBhZGREb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCUFzc2VydC5pc05vdE51bGwobGlzdGVuZXIpOwoJCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzID09IG51bGwpIHsKCQkJCWZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycyA9IG5ldyBBcnJheUxpc3QoMSk7CgkJCX0KCQkJaWYgKCFmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMuY29udGFpbnMobGlzdGVuZXIpKQoJCQkJZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzLmFkZChsaXN0ZW5lcik7CgkJfQoJfQoKCS8qKgoJICogQWRkcyB0aGUgcG9zaXRpb24gdG8gdGhlIGRvY3VtZW50J3MgZGVmYXVsdCBwb3NpdGlvbiBjYXRlZ29yeS4gVGhlCgkgKiBkZWZhdWx0IGNhdGVnb3J5IG11c3QgYmUgc3BlY2lmaWVkIGJ5IHRoZSBpbXBsZW1lbnRlci4gQSBwb3NpdGlvbiB0aGF0CgkgKiBoYXMgYmVlbiBhZGRlZCB0byBhIHBvc2l0aW9uIGNhdGVnb3J5IGlzIHVwZGF0ZWQgYXQgZWFjaCBjaGFuZ2UgYXBwbGllZAoJICogdG8gdGhlIGRvY3VtZW50LgoJICogCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiBwb3NpdGlvbiBpcyBub3QgYSB2YWxpZCByYW5nZSBpbiB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIHZvaWQgYWRkUG9zaXRpb24oUG9zaXRpb24gcG9zaXRpb24pIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkuYWRkUG9zaXRpb24ocG9zaXRpb24pOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjYWRkUG9zaXRpb24KCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHBvc2l0aW9uIGlzIG5vdCBhIHZhbGlkIHJhbmdlIGluIHRoZSBkb2N1bWVudAoJICogQGV4Y2VwdGlvbiBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiB0aGUgY2F0ZWdvcnkgaXMgbm90IGRlZmluZWQgZm9yIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgdm9pZCBhZGRQb3NpdGlvbihTdHJpbmcgY2F0ZWdvcnksIFBvc2l0aW9uIHBvc2l0aW9uKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24sIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLmFkZFBvc2l0aW9uKGNhdGVnb3J5LCBwb3NpdGlvbik7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNhZGRQb3NpdGlvbkNhdGVnb3J5CgkgKi8KCXB1YmxpYyB2b2lkIGFkZFBvc2l0aW9uQ2F0ZWdvcnkoU3RyaW5nIGNhdGVnb3J5KSB7CgkJaW50ZXJuYWxfYWRkUG9zaXRpb25DYXRlZ29yeShjYXRlZ29yeSk7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNhZGRQb3NpdGlvblVwZGF0ZXIKCSAqLwoJcHVibGljIHZvaWQgYWRkUG9zaXRpb25VcGRhdGVyKElQb3NpdGlvblVwZGF0ZXIgdXBkYXRlcikgewoJCWludGVybmFsX2FkZFBvc2l0aW9uVXBkYXRlcih1cGRhdGVyKTsKCX0KCgkvKioKCSAqIEFkZHMgdGhlIGdpdmVuIGRvY3VtZW50IGxpc3RlbmVyIGFzIG9uZSB3aGljaCBpcyBub3RpZmllZCBiZWZvcmUgdGhvc2UKCSAqIGRvY3VtZW50IGxpc3RlbmVycyBhZGRlZCB3aXRoIDxjb2RlPmFkZERvY3VtZW50TGlzdGVuZXI8L2NvZGU+IGFyZQoJICogbm90aWZpZWQuIElmIHRoZSBnaXZlbiBsaXN0ZW5lciBpcyBhbHNvIHJlZ2lzdGVyZWQgdXNpbmcKCSAqIDxjb2RlPmFkZERvY3VtZW50TGlzdGVuZXI8L2NvZGU+IGl0IHdpbGwgYmUgbm90aWZpZWQgdHdpY2UuIElmIHRoZQoJICogbGlzdGVuZXIgaXMgYWxyZWFkeSByZWdpc3RlcmVkIG5vdGhpbmcgaGFwcGVucy4KCSAqIDxwPgoJICogCgkgKiBUaGlzIG1ldGhvZCBpcyBub3QgZm9yIHB1YmxpYyB1c2UsIGl0IG1heSBvbmx5IGJlIGNhbGxlZCBieQoJICogaW1wbGVtZW50ZXJzIG9mIDxjb2RlPklEb2N1bWVudEFkYXB0ZXI8L2NvZGU+IGFuZCBvbmx5IGlmIHRob3NlCgkgKiBpbXBsZW1lbnRlcnMgbmVlZCB0byBpbXBsZW1lbnQgPGNvZGU+SURvY3VtZW50TGlzdGVuZXI8L2NvZGU+LgoJICogCgkgKiBAcGFyYW0gZG9jdW1lbnRBZGFwdGVyCgkgKiAgICAgICAgICAgIHRoZSBsaXN0ZW5lciB0byBiZSBhZGRlZCBhcyBwcmVub3RpZmllZCBkb2N1bWVudCBsaXN0ZW5lcgoJICovCglwdWJsaWMgdm9pZCBhZGRQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXIoSURvY3VtZW50TGlzdGVuZXIgZG9jdW1lbnRBZGFwdGVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmIChmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycyAhPSBudWxsKSB7CgkJCQlpbnQgcHJldmlvdXNTaXplID0gZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJSURvY3VtZW50TGlzdGVuZXJbXSBsaXN0ZW5lcnMgPSBuZXcgSURvY3VtZW50TGlzdGVuZXJbcHJldmlvdXNTaXplICsgMV07CgkJCQlTeXN0ZW0uYXJyYXljb3B5KGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLCAwLCBsaXN0ZW5lcnMsIDAsIHByZXZpb3VzU2l6ZSk7CgkJCQlsaXN0ZW5lcnNbcHJldmlvdXNTaXplXSA9IGRvY3VtZW50QWRhcHRlcjsKCQkJCWZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQl9CgkJCWVsc2UgewoJCQkJZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMgPSBuZXcgSURvY3VtZW50TGlzdGVuZXJbMV07CgkJCQlmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVyc1swXSA9IGRvY3VtZW50QWRhcHRlcjsKCQkJfQoJCX0KCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIGphdmEubGFuZy5DaGFyU2VxdWVuY2UjY2hhckF0KGludCkKCSAqLwoJcHVibGljIGNoYXIgY2hhckF0KGludCBhcmcwKSB7CgkJdHJ5IHsKCQkJcmV0dXJuIGdldENoYXIoMCk7CgkJfQoJCWNhdGNoIChCYWRMb2NhdGlvbkV4Y2VwdGlvbiBlKSB7CgkJCXRocm93IG5ldyBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uKCk7CgkJfQoJfQoKCS8qKgoJICogVGhpcyBmb3JtIG9mIHRoZSBBUEkgcmVtb3ZlcyBhbGwgcmVhZCBvbmx5IHBvc2l0aW9ucywgYXMgc2hvdWxkIGJlIGRvbmUKCSAqIHdlICdzZXRUZXh0JyBpcyBjYWxsZWQuIE5vdGU6IGFuIGFsdGVybmF0aXZlIGFsZ29yaXRobSBtYXkgc2ltcGx5CgkgKiByZW1vdmUgdGhlIGNhdGVnb3J5IChhbmQgaXQgd291bGQgZ2V0IGFkZGVkIGJhY2sgaW4gbGF0ZXIsIGlmL3doZW4KCSAqIHJlYWRvbmx5IHJlZ2lvbnMgYWRkZWQuCgkgKi8KCXByaXZhdGUgdm9pZCBjbGVhclJlYWRPbmx5KCkgewoJCVBvc2l0aW9uW10gcG9zaXRpb25zID0gbnVsbDsKCQl0cnkgewoJCQlwb3NpdGlvbnMgPSBnZXRQb3NpdGlvbnMoUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlkpOwoJCX0KCQljYXRjaCAoQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiBlKSB7CgkJCUxvZ2dlci5sb2dFeGNlcHRpb24oInByb2dyYW0gZXJyb3I6IHNob3VsZCBuZXZlciBvY2N1ciIsIGUpOyAvLyROT04tTkxTLTEkCgkJfQoJCWZvciAoaW50IGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7CgkJCVBvc2l0aW9uIHBvc2l0aW9uID0gcG9zaXRpb25zW2ldOwoJCQkvLyBub3RlIHdlIGRvbid0IGZpcmUgdGhlICJhYm91dCB0byBjaGFuZ2UiIG9yICJjaGFuZ2VkIiBldmVudHMsCgkJCS8vIHNpbmNlIHByZXN1bWFibHksIHRleHQgaXMgYWxsIGdvaW5nIGF3YXkgYW5kIGJlaW5nIHJlcGxhY2VkCgkJCS8vIGFueXdheS4KCQkJcG9zaXRpb24uZGVsZXRlKCk7CgkJfQoJfQoKCglwdWJsaWMgdm9pZCBjbGVhclJlYWRPbmx5KGludCBzdGFydE9mZnNldCwgaW50IGxlbmd0aCkgewoJCS8vIFRPRE8gRFcgSSBzdGlsbCBuZWVkIHRvIGltcGxlbWVudCBzbWFydGVyIGFsZ29yaXRobSB0aGF0CgkJLy8gYWR1c3QgZXhpc3RpbmcgUk8gcmVnaW9ucywgaWYgbmVlZGVkLiBGb3Igbm93LCBJJ2xsIGp1c3QKCQkvLyByZW1vdmUgYW55IHRoYXQgb3ZlcmxhcC4KCQl0cnkgewoJCQlQb3NpdGlvbltdIHBvc2l0aW9ucyA9IGdldFBvc2l0aW9ucyhSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSk7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7CgkJCQlQb3NpdGlvbiBwb3NpdGlvbiA9IHBvc2l0aW9uc1tpXTsKCQkJCWlmIChwb3NpdGlvbi5vdmVybGFwc1dpdGgoc3RhcnRPZmZzZXQsIGxlbmd0aCkpIHsKCQkJCQlTdHJpbmcgZWZmZWN0ZWRUZXh0ID0gdGhpcy5nZXQoc3RhcnRPZmZzZXQsIGxlbmd0aCk7CgkJCQkJLy8gZkRvY3VtZW50RXZlbnQgPSBuZXcgRG9jdW1lbnRFdmVudCh0aGlzLCBzdGFydE9mZnNldCwKCQkJCQkvLyBsZW5ndGgsIGVmZmVjdGVkVGV4dCk7CgkJCQkJZmlyZVJlYWRPbmx5QWJvdXRUb0JlQ2hhbmdlZCgpOwoJCQkJCXBvc2l0aW9uLmRlbGV0ZSgpOwoJCQkJCU5vQ2hhbmdlRXZlbnQgbm9DaGFuZ2VFdmVudCA9IG5ldyBOb0NoYW5nZUV2ZW50KHRoaXMsIG51bGwsIGVmZmVjdGVkVGV4dCwgc3RhcnRPZmZzZXQsIGxlbmd0aCk7CgkJCQkJbm9DaGFuZ2VFdmVudC5yZWFzb24gPSBOb0NoYW5nZUV2ZW50LlJFQURfT05MWV9TVEFURV9DSEFOR0U7CgkJCQkJZmlyZVJlYWRPbmx5U3RydWN0dXJlZERvY3VtZW50RXZlbnQobm9DaGFuZ2VFdmVudCk7CgkJCQl9CgkJCX0KCQl9CgkJY2F0Y2ggKEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gZSkgewoJCQkvLyBqdXN0IG1lYW5zIG5vIHJlYWRvbmx5IHJlZ2lvbnMgYmVlbiBkZWZpbmVkIHlldAoJCQkvLyBzbyBub3RoaW5nIHRvIGRvLgoJCX0KCX0KCgkvKioKCSAqIENvbXB1dGVzIHRoZSBpbmRleCBhdCB3aGljaCBhIDxjb2RlPlBvc2l0aW9uPC9jb2RlPiB3aXRoIHRoZQoJICogc3BlY2lmaWVkIG9mZnNldCB3b3VsZCBiZSBpbnNlcnRlZCBpbnRvIHRoZSBnaXZlbiBjYXRlZ29yeS4gQXMgdGhlCgkgKiBvcmRlcmluZyBpbnNpZGUgYSBjYXRlZ29yeSBvbmx5IGRlcGVuZHMgb24gdGhlIG9mZnNldCwgdGhlIGluZGV4IG11c3QKCSAqIGJlIGNob29zZW4gdG8gYmUgdGhlIGZpcnN0IG9mIGFsbCBwb3NpdGlvbnMgd2l0aCB0aGUgc2FtZSBvZmZzZXQuCgkgKiAKCSAqIEBwYXJhbSBjYXRlZ29yeQoJICogICAgICAgICAgICB0aGUgY2F0ZWdvcnkgaW4gd2hpY2ggd291bGQgYmUgYWRkZWQKCSAqIEBwYXJhbSBvZmZzZXQKCSAqICAgICAgICAgICAgdGhlIHBvc2l0aW9uIG9mZnNldCB0byBiZSBjb25zaWRlcmVkCgkgKiBAcmV0dXJuIHRoZSBpbmRleCBpbnRvIHRoZSBjYXRlZ29yeQoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgaWYgb2Zmc2V0IGlzIGludmFsaWQgaW4gdGhpcyBkb2N1bWVudAoJICogQGV4Y2VwdGlvbiBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBpZiBjYXRlZ29yeSBpcyB1bmRlZmluZWQgaW4gdGhpcyBkb2N1bWVudAoJICovCglwdWJsaWMgaW50IGNvbXB1dGVJbmRleEluQ2F0ZWdvcnkoU3RyaW5nIGNhdGVnb3J5LCBpbnQgb2Zmc2V0KSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uLCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0UG9zaXRpb25NYW5hZ2VyKCkuY29tcHV0ZUluZGV4SW5DYXRlZ29yeShjYXRlZ29yeSwgb2Zmc2V0KTsKCX0KCgkvKioKCSAqIENvbXB1dGVzIHRoZSBudW1iZXIgb2YgbGluZXMgaW4gdGhlIGdpdmVuIHRleHQuIEZvciBhIGdpdmVuIGltcGxlbWVudGVyCgkgKiBvZiB0aGlzIGludGVyZmFjZSB0aGlzIG1ldGhvZCByZXR1cm5zIHRoZSBzYW1lIHJlc3VsdCBhcwoJICogPGNvZGU+c2V0KHRleHQpOyBnZXROdW1iZXJPZkxpbmVzKCk8L2NvZGU+LgoJICogCgkgKiBAcGFyYW0gdGV4dAoJICogICAgICAgICAgICB0aGUgdGV4dCB3aG9zZSBudW1iZXIgb2YgbGluZXMgc2hvdWxkIGJlIGNvbXB1dGVkCgkgKiBAcmV0dXJuIHRoZSBudW1iZXIgb2YgbGluZXMgaW4gdGhlIGdpdmVuIHRleHQKCSAqLwoJcHVibGljIGludCBjb21wdXRlTnVtYmVyT2ZMaW5lcyhTdHJpbmcgdGV4dCkgewoJCXJldHVybiBnZXRUcmFja2VyKCkuY29tcHV0ZU51bWJlck9mTGluZXModGV4dCk7Cgl9CgoJLyoqCgkgKiBDb21wdXRlcyB0aGUgcGFydGl0aW9uaW5nIG9mIHRoZSBnaXZlbiBkb2N1bWVudCByYW5nZSB1c2luZyB0aGUKCSAqIGRvY3VtZW50J3MgcGFydGl0aW9uZXIuCgkgKiAKCSAqIEBwYXJhbSBvZmZzZXQKCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50IG9mZnNldCBhdCB3aGljaCB0aGUgcmFuZ2Ugc3RhcnRzCgkgKiBAcGFyYW0gbGVuZ3RoCgkgKiAgICAgICAgICAgIHRoZSBsZW5ndGggb2YgdGhlIGRvY3VtZW50IHJhbmdlCgkgKiBAcmV0dXJuIGEgc3BlY2lmaWNhdGlvbiBvZiB0aGUgcmFuZ2UncyBwYXJ0aXRpb25pbmcKCSAqIEB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqIEB0aHJvd3MgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uCgkgKi8KCXB1YmxpYyBJVHlwZWRSZWdpb25bXSBjb21wdXRlUGFydGl0aW9uaW5nKGludCBvZmZzZXQsIGludCBsZW5ndGgpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJSVR5cGVkUmVnaW9uW10gdHlwZWRSZWdpb25zID0gbnVsbDsKCQl0cnkgewoJCQl0eXBlZFJlZ2lvbnMgPSBjb21wdXRlUGFydGl0aW9uaW5nKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcsIG9mZnNldCwgbGVuZ3RoLCBmYWxzZSk7CgkJfQoJCWNhdGNoIChCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24gZSkgewoJCQkvLyBpbXBvc3NpYmxlIGluIHRoaXMgY29udGV4dAoJCQl0aHJvdyBuZXcgRXJyb3IoZSk7CgkJfQoJCWlmICh0eXBlZFJlZ2lvbnMgPT0gbnVsbCkgewoJCQl0eXBlZFJlZ2lvbnMgPSBuZXcgSVR5cGVkUmVnaW9uWzBdOwoJCX0KCQlyZXR1cm4gdHlwZWRSZWdpb25zOwoJfQoKCglwdWJsaWMgSVR5cGVkUmVnaW9uW10gY29tcHV0ZVBhcnRpdGlvbmluZyhTdHJpbmcgcGFydGl0aW9uaW5nLCBpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoLCBib29sZWFuIGluY2x1ZGVaZXJvTGVuZ3RoUGFydGl0aW9ucykgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uLCBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24gewoJCWlmICgoMCA+IG9mZnNldCkgfHwgKDAgPiBsZW5ndGgpIHx8IChvZmZzZXQgKyBsZW5ndGggPiBnZXRMZW5ndGgoKSkpCgkJCXRocm93IG5ldyBCYWRMb2NhdGlvbkV4Y2VwdGlvbigpOwoKCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lciA9IGdldERvY3VtZW50UGFydGl0aW9uZXIocGFydGl0aW9uaW5nKTsKCgkJaWYgKHBhcnRpdGlvbmVyIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKQoJCQlyZXR1cm4gKChJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjIpIHBhcnRpdGlvbmVyKS5jb21wdXRlUGFydGl0aW9uaW5nKG9mZnNldCwgbGVuZ3RoLCBpbmNsdWRlWmVyb0xlbmd0aFBhcnRpdGlvbnMpOwoJCWVsc2UgaWYgKHBhcnRpdGlvbmVyICE9IG51bGwpCgkJCXJldHVybiBwYXJ0aXRpb25lci5jb21wdXRlUGFydGl0aW9uaW5nKG9mZnNldCwgbGVuZ3RoKTsKCQllbHNlIGlmIChJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HLmVxdWFscyhwYXJ0aXRpb25pbmcpKQoJCQlyZXR1cm4gbmV3IFR5cGVkUmVnaW9uW117bmV3IFR5cGVkUmVnaW9uKG9mZnNldCwgbGVuZ3RoLCBERUZBVUxUX0NPTlRFTlRfVFlQRSl9OwoJCWVsc2UKCQkJdGhyb3cgbmV3IEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbigpOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjY29udGFpbnNQb3NpdGlvbgoJICovCglwdWJsaWMgYm9vbGVhbiBjb250YWluc1Bvc2l0aW9uKFN0cmluZyBjYXRlZ29yeSwgaW50IG9mZnNldCwgaW50IGxlbmd0aCkgewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5jb250YWluc1Bvc2l0aW9uKGNhdGVnb3J5LCBvZmZzZXQsIGxlbmd0aCk7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNjb250YWluc1Bvc2l0aW9uQ2F0ZWdvcnkKCSAqLwoJcHVibGljIGJvb2xlYW4gY29udGFpbnNQb3NpdGlvbkNhdGVnb3J5KFN0cmluZyBjYXRlZ29yeSkgewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5jb250YWluc1Bvc2l0aW9uQ2F0ZWdvcnkoY2F0ZWdvcnkpOwoJfQoKCXB1YmxpYyBib29sZWFuIGNvbnRhaW5zUmVhZE9ubHkoaW50IHN0YXJ0T2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJYm9vbGVhbiByZXN1bHQgPSBmYWxzZTsKCQl0cnkgewoJCQlQb3NpdGlvbltdIHBvc2l0aW9ucyA9IGdldFBvc2l0aW9ucyhSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSk7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7CgkJCQlQb3NpdGlvbiBwb3NpdGlvbiA9IHBvc2l0aW9uc1tpXTsKCQkJCWlmIChwb3NpdGlvbi5vdmVybGFwc1dpdGgoc3RhcnRPZmZzZXQsIGxlbmd0aCkpIHsKCQkJCQlyZXN1bHQgPSB0cnVlOwoJCQkJCWJyZWFrOwoJCQkJfQoJCQl9CgkJfQoJCWNhdGNoIChCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIGUpIHsKCQkJLy8ganVzdCBtZWFucyBubyByZWFkb25seSByZWdpb25zIGJlZW4gZGVmaW5lZCB5ZXQKCQkJLy8gc28gb2J2aW91c2x5IGZhbHNlCgkJCXJlc3VsdCA9IGZhbHNlOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXByaXZhdGUgdm9pZCBleGVjdXRlUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMoKSB7CgkJaWYgKGZTdG9wcGVkQ291bnQgPiAwKQoJCQlyZXR1cm47CgkJd2hpbGUgKGZQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlcyAhPSBudWxsKSB7CgkJCUxpc3QgY2hhbmdlcyA9IGZQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlczsKCQkJZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzID0gbnVsbDsKCQkJSXRlcmF0b3IgZSA9IGNoYW5nZXMuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCQlSZWdpc3RlcmVkUmVwbGFjZSByZXBsYWNlID0gKFJlZ2lzdGVyZWRSZXBsYWNlKSBlLm5leHQoKTsKCQkJCXJlcGxhY2UuZlJlcGxhY2UucGVyZm9ybSh0aGlzLCByZXBsYWNlLmZPd25lcik7CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2VkKCkgewoJCS8vIG1vc3QgRG9jdW1lbnRBYm91dFRvQmVDaGFuZ2VkIGxpc3RlbmVycyBkbyBub3QgYW50aWNpcGF0ZQoJCS8vIERvY3VtZW50RXZlbnQgPT0gbnVsbC4gU28gbWFrZSBzdXJlIGRvY3VtZW50RXZlbnQgaXMgbm90CgkJLy8gbnVsbC4gKHRoaXMgc2hvdWxkIG5ldmVyIGhhcHBlbiwgeWV0IGl0IGRvZXMgc29tZXRpbWVzKQoJCWlmIChmRG9jdW1lbnRFdmVudCA9PSBudWxsKSB7CgkJCWZEb2N1bWVudEV2ZW50ID0gbmV3IE51bGxEb2N1bWVudEV2ZW50KCk7CgkJfQoKCQlfZmlyZVN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2UoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMpOwoJCS8vIE5vdGU6IHRoZSBkb2NFdmVudCBpcyBjcmVhdGVkIGluIHJlcGxhY2VUZXh0IEFQSSEgKG9yIHNldCBUZXh0KQoJCV9maXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzKTsKCQlub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0Fib3V0VG9DaGFuZ2UoZkRvY3VtZW50RXZlbnQpOwoJCV9maXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlKGZEb2N1bWVudExpc3RlbmVycyk7Cgl9CgoJLyoqCgkgKiBGaXJlcyB0aGUgZG9jdW1lbnQgcGFydGl0aW9uaW5nIGNoYW5nZWQgbm90aWZpY2F0aW9uIHRvIGFsbCByZWdpc3RlcmVkCgkgKiBkb2N1bWVudCBwYXJ0aXRpb25pbmcgbGlzdGVuZXJzLiBVc2VzIGEgcm9idXN0IGl0ZXJhdG9yLgoJICogCgkgKiBAcGFyYW0gZXZlbnQKCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50IHBhcnRpdGlvbmluZyBjaGFuZ2VkIGV2ZW50CgkgKiAKCSAqIEBzZWUgSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24yCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpcmVEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWQoRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkRXZlbnQgZXZlbnQpIHsKCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzID09IG51bGwgfHwgZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzLnNpemUoKSA9PSAwKQoJCQlyZXR1cm47CgoJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzKTsKCQlJdGVyYXRvciBlID0gbGlzdC5pdGVyYXRvcigpOwoJCXdoaWxlIChlLmhhc05leHQoKSkgewoJCQlJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lciBsID0gKElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKSBlLm5leHQoKTsKCQkJaWYgKGwgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbjIpIHsKCQkJCUlEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uMiBleHRlbnNpb24yID0gKElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uMikgbDsKCQkJCWV4dGVuc2lvbjIuZG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkKGV2ZW50KTsKCQkJfQoJCQllbHNlIGlmIChsIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24pIHsKCQkJCUlEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uIGV4dGVuc2lvbiA9IChJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbikgbDsKCQkJCWV4dGVuc2lvbi5kb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWQodGhpcywgZXZlbnQuZ2V0Q292ZXJhZ2UoKSk7CgkJCX0KCQkJZWxzZSB7CgkJCQlsLmRvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZCh0aGlzKTsKCQkJfQoJCX0KCgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVSZWFkT25seUFib3V0VG9CZUNoYW5nZWQoKSB7CgkJX2ZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzKTsKCQkvLyBOb3RlOiB0aGUgZG9jRXZlbnQgaXMgY3JlYXRlZCBpbiByZXBsYWNlVGV4dCBBUEkhIChvciBzZXQgVGV4dCkKCQkvLyBfZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZShmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycyk7CgkJLy8gX2ZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2UoZkRvY3VtZW50TGlzdGVuZXJzKTsKCX0KCglwcml2YXRlIHZvaWQgZmlyZVJlYWRPbmx5U3RydWN0dXJlZERvY3VtZW50RXZlbnQoTm9DaGFuZ2VFdmVudCBldmVudCkgewoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgZXZlbnQpOwoJCS8vIF9maXJlRG9jdW1lbnRDaGFuZ2VkKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJLy8gX2ZpcmVEb2N1bWVudENoYW5nZWQoZkRvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJLy8gX2NsZWFyRG9jdW1lbnRFdmVudCgpOwoJfQoKCXByaXZhdGUgdm9pZCBmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoTm9DaGFuZ2VFdmVudCBldmVudCkgewoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJbm90aWZ5RG9jdW1lbnRQYXJ0aXRpb25lcnNEb2N1bWVudENoYW5nZWQoZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZEb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCV9jbGVhckRvY3VtZW50RXZlbnQoKTsKCX0KCglwcml2YXRlIHZvaWQgZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KFJlZ2lvbkNoYW5nZWRFdmVudCBldmVudCkgewoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJbm90aWZ5RG9jdW1lbnRQYXJ0aXRpb25lcnNEb2N1bWVudENoYW5nZWQoZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZEb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCV9jbGVhckRvY3VtZW50RXZlbnQoKTsKCX0KCglwcml2YXRlIHZvaWQgZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KFJlZ2lvbnNSZXBsYWNlZEV2ZW50IGV2ZW50KSB7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0RvY3VtZW50Q2hhbmdlZChldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZkRvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJX2NsZWFyRG9jdW1lbnRFdmVudCgpOwoJfQoKCXByaXZhdGUgdm9pZCBmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoU3RydWN0dXJlZERvY3VtZW50UmVnaW9uc1JlcGxhY2VkRXZlbnQgZXZlbnQpIHsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCW5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzRG9jdW1lbnRDaGFuZ2VkKGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfY2xlYXJEb2N1bWVudEV2ZW50KCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBkb2N1bWVudCdzIGNvbXBsZXRlIHRleHQuCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0KCkgewoJCXJldHVybiBnZXRTdG9yZSgpLmdldCgwLCBnZXRMZW5ndGgoKSk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGxlbmd0aCBjaGFyYWN0ZXJzIGZyb20gdGhlIGRvY3VtZW50J3MgdGV4dCBzdGFydGluZyBmcm9tIHRoZQoJICogc3BlY2lmaWVkIHBvc2l0aW9uLgoJICogCgkgKiBAdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHRoZSByYW5nZSBpcyBub3QgdmFsaWQgaW4gdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0KGludCBvZmZzZXQsIGludCBsZW5ndGgpIHsKCQlTdHJpbmcgcmVzdWx0ID0gbnVsbDsKCQlpbnQgbXlMZW5ndGggPSBnZXRMZW5ndGgoKTsKCQlpZiAoMCA+IG9mZnNldCkKCQkJb2Zmc2V0ID0gMDsKCQlpZiAoMCA+IGxlbmd0aCkKCQkJbGVuZ3RoID0gMDsKCQlpZiAob2Zmc2V0ICsgbGVuZ3RoID4gbXlMZW5ndGgpIHsKCQkJLy8gZmlyc3QgdHJ5IGFkanVzdGluZyBsZW5ndGggdG8gZml0CgkJCWludCBsZXNzTGVuZ3RoID0gbXlMZW5ndGggLSBvZmZzZXQ7CgkJCWlmICgobGVzc0xlbmd0aCA+PSAwKSAmJiAob2Zmc2V0ICsgbGVzc0xlbmd0aCA9PSBteUxlbmd0aCkpIHsKCQkJCWxlbmd0aCA9IGxlc3NMZW5ndGg7CgkJCX0KCQkJZWxzZSB7CgkJCQkvLyBzZWNvbmQsIHRyeSBvZmZzZXQKCQkJCWludCBtb3JlT2Zmc2V0ID0gbXlMZW5ndGggLSBsZW5ndGg7CgkJCQlpZiAoKG1vcmVPZmZzZXQgPj0gMCkgJiYgKG1vcmVPZmZzZXQgKyBsZW5ndGggPT0gbXlMZW5ndGgpKSB7CgkJCQkJb2Zmc2V0ID0gbW9yZU9mZnNldDsKCQkJCX0KCQkJCWVsc2UgewoJCQkJCS8vIGNhbiBoYXBwZW4gaWYgbXlMZW5ndGggaXMgMC4KCQkJCQkvLyBubyBhZGp1c3RtZW50IHBvc3NpYmxlLgoJCQkJCXJlc3VsdCA9IG5ldyBTdHJpbmcoKTsKCQkJCX0KCQkJfQoKCQl9CgkJaWYgKHJlc3VsdCA9PSBudWxsKSB7CgkJCXJlc3VsdCA9IGdldFN0b3JlKCkuZ2V0KG9mZnNldCwgbGVuZ3RoKTsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCglwdWJsaWMgT2JqZWN0IGdldEFkYXB0ZXIoQ2xhc3MgYWRhcHRlcikgewoJCXJldHVybiBQbGF0Zm9ybS5nZXRBZGFwdGVyTWFuYWdlcigpLmdldEFkYXB0ZXIodGhpcywgYWRhcHRlcik7Cgl9CgoJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBnZXRDYWNoZWREb2N1bWVudFJlZ2lvbigpIHsKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlc3VsdCA9IG51bGw7CgkJaWYgKFVTRV9MT0NBTF9USFJFQUQpIHsKCQkJcmVzdWx0ID0gZkN1cnJlbnREb2N1bW5ldFJlZ2lvbkNhY2hlLmdldCgpOwoJCX0KCQllbHNlIHsKCQkJcmVzdWx0ID0gY2FjaGVkRG9jdW1lbnRSZWdpb247CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNnZXRDaGFyCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiBwb3NpdGlvbiBpcyBub3QgYSB2YWxpZCByYW5nZSBpbiB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIGNoYXIgZ2V0Q2hhcihpbnQgcG9zKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCWNoYXIgcmVzdWx0ID0gMHgwMDsKCQl0cnkgewoJCQlyZXN1bHQgPSBnZXRTdG9yZSgpLmdldChwb3MpOwoJCX0KCQljYXRjaCAoSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbiBlKSB7CgkJCXRocm93IG5ldyBCYWRMb2NhdGlvbkV4Y2VwdGlvbihlLmdldExvY2FsaXplZE1lc3NhZ2UoKSk7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSB0eXBlIG9mIHRoZSBkb2N1bWVudCBwYXJ0aXRpb24gY29udGFpbmluZyB0aGUgZ2l2ZW4KCSAqIGNoYXJhY3RlciBwb3NpdGlvbi4KCSAqLwoJcHVibGljIFN0cmluZyBnZXRDb250ZW50VHlwZShpbnQgb2Zmc2V0KSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXREb2N1bWVudFBhcnRpdGlvbmVyKCkuZ2V0Q29udGVudFR5cGUob2Zmc2V0KTsKCX0KCgoJcHVibGljIFN0cmluZyBnZXRDb250ZW50VHlwZShTdHJpbmcgcGFydGl0aW9uaW5nLCBpbnQgb2Zmc2V0LCBib29sZWFuIHByZWZlck9wZW5QYXJ0aXRpb25zKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24sIEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiB7CgkJaWYgKCgwID4gb2Zmc2V0KSB8fCAob2Zmc2V0ID4gZ2V0TGVuZ3RoKCkpKQoJCQl0aHJvdyBuZXcgQmFkTG9jYXRpb25FeGNlcHRpb24oKTsKCgkJSURvY3VtZW50UGFydGl0aW9uZXIgcGFydGl0aW9uZXIgPSBnZXREb2N1bWVudFBhcnRpdGlvbmVyKHBhcnRpdGlvbmluZyk7CgoJCWlmIChwYXJ0aXRpb25lciBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMikKCQkJcmV0dXJuICgoSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKSBwYXJ0aXRpb25lcikuZ2V0Q29udGVudFR5cGUob2Zmc2V0LCBwcmVmZXJPcGVuUGFydGl0aW9ucyk7CgkJZWxzZSBpZiAocGFydGl0aW9uZXIgIT0gbnVsbCkKCQkJcmV0dXJuIHBhcnRpdGlvbmVyLmdldENvbnRlbnRUeXBlKG9mZnNldCk7CgkJZWxzZSBpZiAoSVN0cnVjdHVyZWRQYXJ0aXRpb25pbmcuREVGQVVMVF9TVFJVQ1RVUkVEX1BBUlRJVElPTklORy5lcXVhbHMocGFydGl0aW9uaW5nKSkKCQkJcmV0dXJuIERFRkFVTFRfQ09OVEVOVF9UWVBFOwoJCWVsc2UKCQkJdGhyb3cgbmV3IEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbigpOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I2dldERlZmF1bHRMaW5lRGVsaW1pdGVyKCkKCSAqLwoJcHVibGljIFN0cmluZyBnZXREZWZhdWx0TGluZURlbGltaXRlcigpIHsKCQkvLyBzcGVjaWZpYyBwcmVmZXJyZWQgbGluZSBkZWxpbWl0ZXIKCQlpZiAocHJlZmVyZWREZWxpbWl0ZXIgIT0gbnVsbCkKCQkJcmV0dXJuIHByZWZlcmVkRGVsaW1pdGVyOwoKCgkJLy8gbm8gbGluZSBkZWxpbWl0ZXIgaGFzIGJlZW4gdXNlZCBzbyBqdXN0IHVzZSBwbGF0Zm9ybSdzIGRlZmF1bHQKCQlTdHJpbmcgbGluZURlbGltaXRlciA9IG51bGw7CgkJU3RyaW5nIHN5c0xpbmVEZWxpbWl0ZXIgPSBQbGF0Zm9ybUxpbmVEZWxpbWl0ZXI7CgkJU3RyaW5nW10gZGVsaW1pdGVycyA9IGdldExlZ2FsTGluZURlbGltaXRlcnMoKTsKCQlBc3NlcnQuaXNUcnVlKGRlbGltaXRlcnMubGVuZ3RoID4gMCk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBkZWxpbWl0ZXJzLmxlbmd0aDsgaSsrKSB7CgkJCWlmIChkZWxpbWl0ZXJzW2ldLmVxdWFscyhzeXNMaW5lRGVsaW1pdGVyKSkgewoJCQkJbGluZURlbGltaXRlciA9IHN5c0xpbmVEZWxpbWl0ZXI7CgkJCQlicmVhazsKCQkJfQoJCX0KCgkJLy8gbm8gcGxhdGZvcm0gZGVmYXVsdCBzbyBqdXN0IHVzZSBmaXJzdCBsZWdhbCBkZWxpbWl0ZXIKCQlpZiAobGluZURlbGltaXRlciA9PSBudWxsKQoJCQlsaW5lRGVsaW1pdGVyID0gZGVsaW1pdGVyc1swXTsKCgkJcmV0dXJuIGxpbmVEZWxpbWl0ZXI7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBkb2N1bWVudCdzIHBhcnRpdGlvbmVyLgoJICogCgkgKiBAc2VlIElEb2N1bWVudFBhcnRpdGlvbmVyCgkgKi8KCXB1YmxpYyBJRG9jdW1lbnRQYXJ0aXRpb25lciBnZXREb2N1bWVudFBhcnRpdGlvbmVyKCkgewoJCXJldHVybiBnZXREb2N1bWVudFBhcnRpdGlvbmVyKElEb2N1bWVudEV4dGVuc2lvbjMuREVGQVVMVF9QQVJUSVRJT05JTkcpOwoJfQoKCglwdWJsaWMgSURvY3VtZW50UGFydGl0aW9uZXIgZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcihTdHJpbmcgcGFydGl0aW9uaW5nKSB7CgoJCUlEb2N1bWVudFBhcnRpdGlvbmVyIGRvY3VtZW50UGFydGl0aW9uZXIgPSBudWxsOwoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgIT0gbnVsbCkgewoJCQlkb2N1bWVudFBhcnRpdGlvbmVyID0gKElEb2N1bWVudFBhcnRpdGlvbmVyKSBmRG9jdW1lbnRQYXJ0aXRpb25lcnMuZ2V0KHBhcnRpdGlvbmluZyk7CgkJfQoJCXJldHVybiBkb2N1bWVudFBhcnRpdGlvbmVyOwoJfQoKCXB1YmxpYyBFbmNvZGluZ01lbWVudG8gZ2V0RW5jb2RpbmdNZW1lbnRvKCkgewoJCXJldHVybiBlbmNvZGluZ01lbWVudG87Cgl9CgoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZ2V0Rmlyc3RTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24oKSB7CgkJLy8gc2hvdWxkIHdlIHVwZGF0ZSBjYWNoZWROb2RlPwoJCS8vIFdlIHNob3VsZCB0byBrZWVwIGNvbnNpc3RlbnQgcGhpbG9zb3BoeSBvZiByZW1lbWJlcmluZyBsYXN0CgkJLy8gcmVxdWVzdGVkIHBvc2l0aW9uLAoJCS8vIGZvciBlZmZpY2llbmN5LgoJCXNldENhY2hlZERvY3VtZW50UmVnaW9uKGZpcnN0RG9jdW1lbnRSZWdpb24pOwoJCXJldHVybiBmaXJzdERvY3VtZW50UmVnaW9uOwoJfQoKCXB1YmxpYyBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGdldExhc3RTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24oKSB7CgkJLy8gc2hvdWxkIHdlIHVwZGF0ZSBjYWNoZWROb2RlPwoJCS8vIFdlIHNob3VsZCB0byBrZWVwIGNvbnNpc3RlbnQgcGhpbG9zb3BoeSBvZiByZW1lbWJlcmluZyBsYXN0CgkJLy8gcmVxdWVzdGVkIHBvc2l0aW9uLAoJCS8vIGZvciBlZmZpY2llbmN5LgoJCXNldENhY2hlZERvY3VtZW50UmVnaW9uKGxhc3REb2N1bWVudFJlZ2lvbik7CgkJcmV0dXJuIGxhc3REb2N1bWVudFJlZ2lvbjsKCX0KCgkvKgoJICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gcGFydGl0aW9ucwoJICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoJICovCglwdWJsaWMgU3RyaW5nW10gZ2V0TGVnYWxDb250ZW50VHlwZXMoKSB7CgkJU3RyaW5nW10gcmVzdWx0ID0gbnVsbDsKCQl0cnkgewoJCQlyZXN1bHQgPSBnZXRMZWdhbENvbnRlbnRUeXBlcyhJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HKTsKCQl9CgkJY2F0Y2ggKEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiBlKSB7CgkJCS8vIGltcG9zc2libGUgaW4gdGhpcyBjb250ZXh0CgkJCXRocm93IG5ldyBFcnJvcihlKTsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCglwdWJsaWMgU3RyaW5nW10gZ2V0TGVnYWxDb250ZW50VHlwZXMoU3RyaW5nIHBhcnRpdGlvbmluZykgdGhyb3dzIEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiB7CgkJSURvY3VtZW50UGFydGl0aW9uZXIgcGFydGl0aW9uZXIgPSBnZXREb2N1bWVudFBhcnRpdGlvbmVyKHBhcnRpdGlvbmluZyk7CgkJaWYgKHBhcnRpdGlvbmVyICE9IG51bGwpCgkJCXJldHVybiBwYXJ0aXRpb25lci5nZXRMZWdhbENvbnRlbnRUeXBlcygpOwoJCWlmIChJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HLmVxdWFscyhwYXJ0aXRpb25pbmcpKQoJCQlyZXR1cm4gbmV3IFN0cmluZ1tde0RFRkFVTFRfQ09OVEVOVF9UWVBFfTsKCQl0aHJvdyBuZXcgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uKCk7Cgl9CgoJLyoKCSAqIC0tLS0tLS0tLS0tLS0tLS0tLSBsaW5lIGRlbGltaXRlciBjb252ZXJzaW9uCgkgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCSAqLwoJcHVibGljIFN0cmluZ1tdIGdldExlZ2FsTGluZURlbGltaXRlcnMoKSB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMZWdhbExpbmVEZWxpbWl0ZXJzKCk7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNnZXRMZW5ndGgKCSAqLwoJcHVibGljIGludCBnZXRMZW5ndGgoKSB7CgkJcmV0dXJuIGdldFN0b3JlKCkuZ2V0TGVuZ3RoKCk7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZERvY3VtZW50I2dldExpbmVEZWxpbWl0ZXIoKQoJICovCglwdWJsaWMgU3RyaW5nIGdldExpbmVEZWxpbWl0ZXIoKSB7CgkJcmV0dXJuIGdldERlZmF1bHRMaW5lRGVsaW1pdGVyKCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBsaW5lIGRlbGltaXRlciBvZiB0aGF0IGxpbmUKCSAqIAoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgdGhlIGxpbmUgbnVtYmVyIGlzIGludmFsaWQgaW4gdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0TGluZURlbGltaXRlcihpbnQgbGluZSkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TGluZURlbGltaXRlcihsaW5lKTsKCX0KCgkvKioKCSAqIFJldHVybnMgYSBkZXNjcmlwdGlvbiBvZiB0aGUgc3BlY2lmaWVkIGxpbmUuIFRoZSBsaW5lIGlzIGRlc2NyaWJlZCBieQoJICogaXRzIG9mZnNldCBhbmQgaXRzIGxlbmd0aCBleGNsdWRpbmcgdGhlIGxpbmUncyBkZWxpbWl0ZXIuCgkgKiAKCSAqIEBwYXJhbSBsaW5lCgkgKiAgICAgICAgICAgIHRoZSBsaW5lIG9mIGludGVyZXN0CgkgKiBAcmV0dXJuIGEgbGluZSBkZXNjcmlwdGlvbgoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgaWYgdGhlIGxpbmUgbnVtYmVyIGlzIGludmFsaWQgaW4gdGhpcyBkb2N1bWVudAoJICovCglwdWJsaWMgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JUmVnaW9uIGdldExpbmVJbmZvcm1hdGlvbihpbnQgbGluZSkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TGluZUluZm9ybWF0aW9uKGxpbmUpOwoJfQoKCS8qKgoJICogUmV0dXJucyBhIGRlc2NyaXB0aW9uIG9mIHRoZSBsaW5lIGF0IHRoZSBnaXZlbiBvZmZzZXQuIFRoZSBkZXNjcmlwdGlvbgoJICogY29udGFpbnMgdGhlIG9mZnNldCBhbmQgdGhlIGxlbmd0aCBvZiB0aGUgbGluZSBleGNsdWRpbmcgdGhlIGxpbmUncwoJICogZGVsaW1pdGVyLgoJICogCgkgKiBAcGFyYW0gb2Zmc2V0CgkgKiAgICAgICAgICAgIHRoZSBvZmZzZXQgd2hvc2UgbGluZSBzaG91bGQgYmUgZGVzY3JpYmVkCgkgKiBAcmV0dXJuIGEgcmVnaW9uIGRlc2NyaWJpbmcgdGhlIGxpbmUKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIG9mZnNldCBpcyBpbnZhbGlkIGluIHRoaXMgZG9jdW1lbnQKCSAqLwoJcHVibGljIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSVJlZ2lvbiBnZXRMaW5lSW5mb3JtYXRpb25PZk9mZnNldChpbnQgb2Zmc2V0KSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lSW5mb3JtYXRpb25PZk9mZnNldChvZmZzZXQpOwoJfQoKCS8qCgkgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGxpbmUgaW5mb3JtYXRpb24KCSAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgkgKi8KCXB1YmxpYyBpbnQgZ2V0TGluZUxlbmd0aChpbnQgbGluZSkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TGluZUxlbmd0aChsaW5lKTsKCX0KCgkvKioKCSAqIERldGVybWluZXMgdGhlIG9mZnNldCBvZiB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIHRoZSBnaXZlbiBsaW5lLgoJICogCgkgKiBAcGFyYW0gbGluZQoJICogICAgICAgICAgICB0aGUgbGluZSBvZiBpbnRlcmVzdAoJICogQHJldHVybiB0aGUgZG9jdW1lbnQgb2Zmc2V0CgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBpZiB0aGUgbGluZSBudW1iZXIgaXMgaW52YWxpZCBpbiB0aGlzIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBpbnQgZ2V0TGluZU9mZnNldChpbnQgbGluZSkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TGluZU9mZnNldChsaW5lKTsKCX0KCglwdWJsaWMgaW50IGdldExpbmVPZk9mZnNldChpbnQgb2Zmc2V0KSB7CgkJaW50IHJlc3VsdCA9IC0xOwoJCXRyeSB7CgkJCXJlc3VsdCA9IGdldFRyYWNrZXIoKS5nZXRMaW5lTnVtYmVyT2ZPZmZzZXQob2Zmc2V0KTsKCQl9CgkJY2F0Y2ggKEJhZExvY2F0aW9uRXhjZXB0aW9uIGUpIHsKCQkJaWYgKExvZ2dlci5ERUJVR19ET0NVTUVOVCkKCQkJCUxvZ2dlci5sb2coTG9nZ2VyLklORk8sICJEZXYuIFByb2dyYW0gSW5mbyBPbmx5OiBJU3RydWN0dXJlZERvY3VtZW50OjpnZXRMaW5lT2ZPZmZzZXQ6IG9mZnNldCBvdXQgb2YgcmFuZ2UsIHplcm8gYXNzdW1lZC4gb2Zmc2V0ID0gIiArIG9mZnNldCwgZSk7IC8vJE5PTi1OTFMtMSQgLy8kTk9OLU5MUy0yJAoJCQlyZXN1bHQgPSAwOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGxpbmVzIGluIHRoaXMgZG9jdW1lbnQKCSAqIAoJICogQHJldHVybiB0aGUgbnVtYmVyIG9mIGxpbmVzIGluIHRoaXMgZG9jdW1lbnQKCSAqLwoJcHVibGljIGludCBnZXROdW1iZXJPZkxpbmVzKCkgewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TnVtYmVyT2ZMaW5lcygpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGxpbmVzIHdoaWNoIGFyZSBvY2N1cGllZCBieSBhIGdpdmVuIHRleHQgcmFuZ2UuCgkgKiAKCSAqIEBwYXJhbSBvZmZzZXQKCSAqICAgICAgICAgICAgdGhlIG9mZnNldCBvZiB0aGUgc3BlY2lmaWVkIHRleHQgcmFuZ2UKCSAqIEBwYXJhbSBsZW5ndGgKCSAqICAgICAgICAgICAgdGhlIGxlbmd0aCBvZiB0aGUgc3BlY2lmaWVkIHRleHQgcmFuZ2UKCSAqIEByZXR1cm4gdGhlIG51bWJlciBvZiBsaW5lcyBvY2N1cGllZCBieSB0aGUgc3BlY2lmaWVkIHJhbmdlCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBpZiBzcGVjaWZpZWQgcmFuZ2UgaXMgaW52YWxpZCBpbiB0aGlzIHRyYWNrZXIKCSAqLwoJcHVibGljIGludCBnZXROdW1iZXJPZkxpbmVzKGludCBvZmZzZXQsIGludCBsZW5ndGgpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldE51bWJlck9mTGluZXMob2Zmc2V0LCBsZW5ndGgpOwoJfQoKCS8qKgoJICogVGhpcyBpcyBwdWJsaWMsIHRlbXBvcmFyaWx5LCBmb3IgdXNlIGJ5IHRhZyBsaWIgY2xhc3Nlcy4KCSAqLwoJcHVibGljIFJlZ2lvblBhcnNlciBnZXRQYXJzZXIoKSB7CgkJaWYgKGZQYXJzZXIgPT0gbnVsbCkgewoJCQl0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJJU3RydWN0dXJlZERvY3VtZW50OjpnZXRQYXJzZXIuIFBhcnNlciBuZWVkcyB0byBiZSBzZXQgYmVmb3JlIHVzZSIpOyAvLyROT04tTkxTLTEkCgkJfQoJCXJldHVybiBmUGFyc2VyOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgZG9jdW1lbnQgcGFydGl0aW9uIGluIHdoaWNoIHRoZSBwb3NpdGlvbiBpcyBsb2NhdGVkLiBUaGUKCSAqIHBhcnRpdGlvbiBpcyBzcGVjaWZpZWQgYXMgdHlwZWQgcmVnaW9uLgoJICovCglwdWJsaWMgSVR5cGVkUmVnaW9uIGdldFBhcnRpdGlvbihpbnQgb2Zmc2V0KSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCUlUeXBlZFJlZ2lvbiBwYXJ0aXRpb24gPSBudWxsOwoJCXRyeSB7CgkJCXBhcnRpdGlvbiA9IGdldFBhcnRpdGlvbihJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HLCBvZmZzZXQsIGZhbHNlKTsKCQl9CgkJY2F0Y2ggKEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiBlKSB7CgkJCXRocm93IG5ldyBFcnJvcihlKTsKCQl9CgkJaWYgKHBhcnRpdGlvbiA9PSBudWxsKSB7CgkJCXRocm93IG5ldyBFcnJvcigpOwoJCX0KCQlyZXR1cm4gcGFydGl0aW9uOwoJfQoKCglwdWJsaWMgSVR5cGVkUmVnaW9uIGdldFBhcnRpdGlvbihTdHJpbmcgcGFydGl0aW9uaW5nLCBpbnQgb2Zmc2V0LCBib29sZWFuIHByZWZlck9wZW5QYXJ0aXRpb25zKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24sIEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiB7CgkJaWYgKCgwID4gb2Zmc2V0KSB8fCAob2Zmc2V0ID4gZ2V0TGVuZ3RoKCkpKQoJCQl0aHJvdyBuZXcgQmFkTG9jYXRpb25FeGNlcHRpb24oKTsKCQlJVHlwZWRSZWdpb24gcmVzdWx0ID0gbnVsbDsKCgkJSURvY3VtZW50UGFydGl0aW9uZXIgcGFydGl0aW9uZXIgPSBnZXREb2N1bWVudFBhcnRpdGlvbmVyKHBhcnRpdGlvbmluZyk7CgoJCWlmIChwYXJ0aXRpb25lciBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMikgewoJCQlyZXN1bHQgPSAoKElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMikgcGFydGl0aW9uZXIpLmdldFBhcnRpdGlvbihvZmZzZXQsIHByZWZlck9wZW5QYXJ0aXRpb25zKTsKCQl9CgkJZWxzZSBpZiAocGFydGl0aW9uZXIgIT0gbnVsbCkgewoJCQlyZXN1bHQgPSBwYXJ0aXRpb25lci5nZXRQYXJ0aXRpb24ob2Zmc2V0KTsKCQl9CgkJZWxzZSBpZiAoSVN0cnVjdHVyZWRQYXJ0aXRpb25pbmcuREVGQVVMVF9TVFJVQ1RVUkVEX1BBUlRJVElPTklORy5lcXVhbHMocGFydGl0aW9uaW5nKSkgewoJCQlyZXN1bHQgPSBuZXcgVHlwZWRSZWdpb24oMCwgZ2V0TGVuZ3RoKCksIERFRkFVTFRfQ09OVEVOVF9UWVBFKTsKCQl9CgkJZWxzZQoJCQl0aHJvdyBuZXcgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uKCk7CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgoJcHVibGljIFN0cmluZ1tdIGdldFBhcnRpdGlvbmluZ3MoKSB7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyA9PSBudWxsKQoJCQlyZXR1cm4gbmV3IFN0cmluZ1swXTsKCQlTdHJpbmdbXSBwYXJ0aXRpb25pbmdzID0gbmV3IFN0cmluZ1tmRG9jdW1lbnRQYXJ0aXRpb25lcnMuc2l6ZSgpXTsKCQlmRG9jdW1lbnRQYXJ0aXRpb25lcnMua2V5U2V0KCkudG9BcnJheShwYXJ0aXRpb25pbmdzKTsKCQlyZXR1cm4gcGFydGl0aW9uaW5nczsKCX0KCgkvKioKCSAqIFJldHVybnMgYWxsIHBvc2l0aW9uIGNhdGVnb3JpZXMgYWRkZWQgdG8gdGhpcyBkb2N1bWVudC4KCSAqLwoJcHVibGljIFN0cmluZ1tdIGdldFBvc2l0aW9uQ2F0ZWdvcmllcygpIHsKCQlyZXR1cm4gZ2V0UG9zaXRpb25NYW5hZ2VyKCkuZ2V0UG9zaXRpb25DYXRlZ29yaWVzKCk7Cgl9CgoJLyoqCgkgKiBAcmV0dXJuIFJldHVybnMgdGhlIHBvc2l0aW9uTWFuYWdlci4KCSAqLwoJcHJpdmF0ZSBHZW5lcmljUG9zaXRpb25NYW5hZ2VyIGdldFBvc2l0aW9uTWFuYWdlcigpIHsKCQlpZiAoZlBvc2l0aW9uTWFuYWdlciA9PSBudWxsKSB7CgkJCWZQb3NpdGlvbk1hbmFnZXIgPSBuZXcgR2VuZXJpY1Bvc2l0aW9uTWFuYWdlcih0aGlzKTsKCQl9CgkJcmV0dXJuIGZQb3NpdGlvbk1hbmFnZXI7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGFsbCBQb3NpdGlvbnMgb2YgdGhlIGdpdmVuIHBvc2l0aW9uIGNhdGVnb3J5LgoJICogCgkgKiBAZXhjZXB0aW9uIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIGNhdGVnb3J5IGlzIG5vdCBkZWZpbmVkIGZvciB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIFBvc2l0aW9uW10gZ2V0UG9zaXRpb25zKFN0cmluZyBjYXRlZ29yeSkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFBvc2l0aW9uTWFuYWdlcigpLmdldFBvc2l0aW9ucyhjYXRlZ29yeSk7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNnZXRQb3NpdGlvblVwZGF0ZXJzCgkgKi8KCXB1YmxpYyBJUG9zaXRpb25VcGRhdGVyW10gZ2V0UG9zaXRpb25VcGRhdGVycygpIHsKCQlyZXR1cm4gZ2V0UG9zaXRpb25NYW5hZ2VyKCkuZ2V0UG9zaXRpb25VcGRhdGVycygpOwoJfQoKCS8qKgoJICogVGhpcyBtZXRob2QgY2FuIHJldHVybiBudWxsLCB3aGljaCBpcyB0aGUgY2FzZSBpZiB0aGUgb2Zmc2V0IGlzIGp1c3QKCSAqIGJlZm9yZSBvciBqdXN0IGFmdGVyIHRoZSBleGlzdGluZyB0ZXh0LiBDb21wYXJlIHdpdGgKCSAqIGdldE5vZGVBdENoYXJhY3Rlck9mZnNldC4KCSAqLwoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZ2V0UmVnaW9uQXRDaGFyYWN0ZXJPZmZzZXQoaW50IG9mZnNldCkgewoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVzdWx0ID0gbnVsbDsKCgkJLy8gRklYTUU6IG5lZWQgdG8gc3luY2ggb24gJ2NhY2hlZFJlZ2lvbicgKGJ1dCBzaW5jZSB0aGF0J3MgYQoJCS8vIGNvbnN0YW50bHkgY2hhbmdpbmcgb2JqZWN0LCB3ZQoJCS8vIGNhbid0LCBzbyBuZWVkIHRvIGFkZCBhICJyZWdpb25fbG9jayIgb2JqZWN0LCBhbmQgdXNlIGl0IGhlcmUsIGFuZAoJCS8vIGluIHJlLXBhcnNlci4KCQkvLyBPaCwgYW5kIG5lZWQgdG8gbWFrZSBzdXJlLCBhZnRlciBzeW5jaCwgdGhhdCB0aGUgcmVnaW9uIGlzIG5vdAoJCS8vIGRlbGV0ZWQsIGFuZCBpZiBzbywgSSBndWVzcyBnbyBiYWNrCgkJLy8gdG8gdGhlIGJlZ2lubmluZyEKCgkJLy8gY2FjaGVkIG5vZGUgY2FuIGJlIG51bGwgd2hlbiBkb2N1bWVudCBpcyBlbXB0eQoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcG90ZW50aWFsQ2FjaGVkUmVnaW9uID0gZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKTsKCQlpZiAocG90ZW50aWFsQ2FjaGVkUmVnaW9uICE9IG51bGwpIHsKCgkJCS8vIAoKCQkJLy8gaWYgd2UgYWxyZWFkeSBoYXZlIHRoZSByaWdodCBub2RlLCByZXR1cm4gdGhhdC4KCQkJaWYgKHBvdGVudGlhbENhY2hlZFJlZ2lvbi5jb250YWluc09mZnNldChvZmZzZXQpKSB7CgkJCQlyZXN1bHQgPSBwb3RlbnRpYWxDYWNoZWRSZWdpb247CgkJCX0KCQkJZWxzZSB7CgkJCQkvLyBmaXJzdCwgZmluZCBvdXQgd2hhdCBkaXJlY3Rpb24gdG8gZ28sIHJlbGF0aXZlIHRvCgkJCQkvLyBjYWNoZWROb2RlLgoJCQkJLy8gbmVnYXRpdmUgbWVhbnMgInRvd2FyZHMgdGhlIGZyb250IiBvZiB0aGUgZmlsZSwKCQkJCS8vIHBvc3RpdGl2ZQoJCQkJLy8gbWVhbnMKCQkJCS8vIHRvd2FyZHMgdGhlIGVuZC4KCQkJCWludCBkaXJlY3Rpb24gPSBvZmZzZXQgLSBwb3RlbnRpYWxDYWNoZWRSZWdpb24uZ2V0U3RhcnQoKTsKCQkJCWlmIChkaXJlY3Rpb24gPCAwKSB7CgkJCQkJLy8gc2VhcmNoIHRvd2FyZHMgYmVnaW5uaW5nCgkJCQkJd2hpbGUgKCFwb3RlbnRpYWxDYWNoZWRSZWdpb24uY29udGFpbnNPZmZzZXQob2Zmc2V0KSkgewoJCQkJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHRlbXBOb2RlID0gcG90ZW50aWFsQ2FjaGVkUmVnaW9uLmdldFByZXZpb3VzKCk7CgkJCQkJCWlmICh0ZW1wTm9kZSA9PSBudWxsKSB7CgkJCQkJCQlicmVhazsKCQkJCQkJfQoJCQkJCQllbHNlIHsKCQkJCQkJCXBvdGVudGlhbENhY2hlZFJlZ2lvbiA9IHRlbXBOb2RlOwoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJLy8gc2VhcmNoIHRvd2FyZHMgZW5kCgkJCQkJLy8gVGhlcmUgaXMgYSBsZWdpdGFtYXQgY29uZGl0aW9uIHdoZXJlIHRoZQoJCQkJCS8vIG9mZnNldCB3aWxsIG5vdCBiZSBjb250YWluZWQgaW4gYW55IG5vZGUsCgkJCQkJLy8gd2hpY2ggaXMgaWYgdGhlIG9mZnNldCBpcyBqdXN0IHBhc3QgdGhlIGxhc3QKCQkJCQkvLyBjaGFyYWN0ZXIgb2YgdGV4dC4KCQkJCQkvLyBBbmQsIHdlIG11c3QgZ2F1cmQgYWdhaW5zdCBzZXR0aW5nIGNhY2hlZE5vZGUgdG8KCQkJCQkvLyBudWxsIQoJCQkJCXdoaWxlICghcG90ZW50aWFsQ2FjaGVkUmVnaW9uLmNvbnRhaW5zT2Zmc2V0KG9mZnNldCkpIHsKCQkJCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiB0ZW1wTm9kZSA9IHBvdGVudGlhbENhY2hlZFJlZ2lvbi5nZXROZXh0KCk7CgkJCQkJCWlmICh0ZW1wTm9kZSA9PSBudWxsKQoJCQkJCQkJYnJlYWs7CgkJCQkJCWVsc2UKCQkJCQkJCXBvdGVudGlhbENhY2hlZFJlZ2lvbiA9IHRlbXBOb2RlOwoJCQkJCX0KCQkJCX0KCQkJfQoJCQlyZXN1bHQgPSBwb3RlbnRpYWxDYWNoZWRSZWdpb247CgkJfQoJCS8vIGp1c3QgdG8gYmUgZG91Ymx5IHN1cmUgd2UgbmV2ZXIgYXNzaWduIG51bGwgdG8gYW4gYWxyZWFkeSB2YWxpZAoJCS8vIGNhY2hlZFJlZ2lvbi4KCQkvLyBJIGJlbGlldmUgYW55IHRpbWUgJ3Jlc3VsdCcgaXMgbnVsbCBhdCB0aGlzIHBvaW50LCB0aGF0IGp1c3QgbWVhbnMKCQkvLyB3ZSBoYXZlIGFuCgkJLy8gZW1wdHkgZG9jdW1lbnQsIGFuZCB0aGUgY2FjaGVkUmVnaW9uIGlzIGFscmVhZHkgbnVsbCwgYnV0IHdlIGNoZWNrCgkJLy8gYW5kIHByaW50CgkJLy8gd2FybmluZywganVzdCBzbyBkdXJpbmcgZGV2ZWxvcG1lbnQgd2UgYmUgc3VyZSB3ZSBuZXZlciBhY2NpZGVudGx5CgkJLy8gYnJlYWsgdGhpcyBhc3N1bXB0aW9uLgoJCWlmIChyZXN1bHQgIT0gbnVsbCkKCQkJc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24ocmVzdWx0KTsKCQllbHNlIGlmIChnZXRDYWNoZWREb2N1bWVudFJlZ2lvbigpICE9IG51bGwpIHsKCQkJdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiUHJvZ3JhbSBFcnJvcjogbm8gcmVnaW9uIGNvdWxkIGJlIGZvdW5kIHRvIGNhY2hlLCBidXQgY2FjaGUgd2FzIG5vbiBudWxsLiBJbmRpY2F0ZXMgY29ycnVwdGVkIG1vZGVsIG9yIHJlZ2lvbiBsaXN0Iik7IC8vJE5PTi1OTFMtMSQKCQl9CgoJCXJldHVybiByZXN1bHQ7Cgl9CgoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25MaXN0IGdldFJlZ2lvbkxpc3QoKSB7CgkJQ29yZU5vZGVMaXN0IHJlc3VsdCA9IG51bGw7CgkJaWYgKGdldENhY2hlZERvY3VtZW50UmVnaW9uKCkgPT0gbnVsbCkKCQkJcmVzdWx0ID0gbmV3IENvcmVOb2RlTGlzdChudWxsKTsKCQllbHNlCgkJCXJlc3VsdCA9IG5ldyBDb3JlTm9kZUxpc3QoZ2V0Rmlyc3RTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24oKSk7CgoJCXJldHVybiByZXN1bHQ7Cgl9CgoKCXB1YmxpYyBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uW10gZ2V0U3RydWN0dXJlZERvY3VtZW50UmVnaW9ucygpIHsKCQlyZXR1cm4gZ2V0U3RydWN0dXJlZERvY3VtZW50UmVnaW9ucygwLCBnZXRMZW5ndGgoKSk7Cgl9CgoJLyoqCgkgKiA8cD4KCSAqIEluIHRoZSBjYXNlIG9mIDAgbGVuZ3RoLCB0aGUgPGNvZGU+SVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbjwvY29kZT4KCSAqIGF0IHRoZSBjaGFyYWN0ZXIgb2Zmc2V0IGlzIHJldHVyZW5lZC4gSW4gb3RoZXIgd29yZHMsIHRoZSByZWdpb24gdG8gdGhlCgkgKiByaWdodCBvZiB0aGUgY2FyZXQgaXMgcmV0dXJuZWQuIGV4Y2VwdCBmb3IgYXQgdGhlIGVuZCBvZiB0aGUgZG9jdW1lbnQsCgkgKiB0aGVuIHRoZSBsYXN0IHJlZ2lvbiBpcyByZXR1cm5lZC4KCSAqIDwvcD4KCSAqIDxwPgoJICogT3RoZXJ3aXNlIGFsbCB0aGUgcmVnaW9ucyAiaW5iZXR3ZWVuIiB0aGUgaW5kaWNhdGVkIHJhbmdlIGFyZSByZXR1cm5lZCwKCSAqIGluY2x1ZGluZyB0aGUgcmVnaW9ucyB3aGljaCBvdmVybGFwIHRoZSByZWdpb24uCgkgKiA8L3A+CgkgKiAKCSAqIDxicj4KCSAqIGVnLgoJICogPHA+CgkgKiA8YnI+CgkgKiBlZy4KCSAqIAoJICogPHByZT4KCSAqICAgICAgICAgICAgICAgICAgICAgICAgJmx0O2h0bWwmZ3Q7WyZsdDtoZWFkJmd0OyZsdDsvaGVhZCZndDtdJmx0Oy9odG1sJmd0OyByZXR1cm5zICZsdDtoZWFkJmd0OywmbHQ7L2hlYWQmZ3Q7CgkgKiA8L3ByZT4KCSAqICAgIDxwcmU+CgkgKiAgICAgICAgICAgICAgICAgICAgICAgICZsdDtodFttbCZndDsmbHQ7aGVhZCZndDsmbHQ7L2hlXWFkJmd0OyZsdDsvaHRtbCZndDsgcmV0dXJucyAmbHQ7aHRtbCZndDssJmx0O2hlYWQmZ3Q7LCZsdDsvaGVhZCZndDsKCSAqIDwvcHJlPgoJICogCgkgKiA8cHJlPgoJICogICAgICAgICAgICAgICAgICAgICAgICAgICZsdDtodG1sJmd0O1smbHQ7aGVhZCZndDsmbHQ7L2hlYWQmZ3Q7XSZsdDsvaHRtbCZndDsgcmV0dXJucyAmbHQ7aGVhZCZndDssJmx0Oy9oZWFkJmd0OwoJICogPC9wcmU+CgkgKiAgICA8cHJlPgoJICogICAgICAgICAgICAgICAgICAgICAgICAgICZsdDtodFttbCZndDsmbHQ7aGVhZCZndDsmbHQ7L2hlXWFkJmd0OyZsdDsvaHRtbCZndDsgcmV0dXJucyAmbHQ7aHRtbCZndDssJmx0O2hlYWQmZ3Q7LCZsdDsvaGVhZCZndDsKCSAqIDwvcHJlPgoJICogCgkgKiA8L3A+CgkgKi8KCXB1YmxpYyBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uW10gZ2V0U3RydWN0dXJlZERvY3VtZW50UmVnaW9ucyhpbnQgc3RhcnQsIGludCBsZW5ndGgpIHsKCgkJaWYgKGxlbmd0aCA8IDApCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oImNhbid0IGhhdmUgbmVnYXRpdmUgbGVuZ3RoIik7IC8vJE5PTi1OTFMtMSQKCgkJLy8gdGhpcyB3aWxsIG1ha2UgdGhlIHJpZ2h0IGVkZ2Ugb2YgdGhlIHJhbmdlIHBvaW50IGludG8gdGhlIHNlbGVjdGlvbgoJCS8vIGVnLiA8aHRtbD5bPGhlYWQ+PC9oZWFkPl08L2h0bWw+CgkJLy8gd2lsbCByZXR1cm4gPGhlYWQ+LDwvaGVhZD4gaW5zdGVhZCBvZiA8aGVhZD4sPC9oZWFkPiw8L2h0bWw+CgkJaWYgKGxlbmd0aCA+IDApCgkJCWxlbmd0aC0tOwoKCQlMaXN0IHJlc3VsdHMgPSBuZXcgQXJyYXlMaXN0KCk7CgoJCS8vIHN0YXJ0IHRocmVhZCBzYWZlIGJsb2NrCgkJdHJ5IHsKCQkJYWNxdWlyZUxvY2soKTsKCgkJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gY3VycmVudFJlZ2lvbiA9IGdldFJlZ2lvbkF0Q2hhcmFjdGVyT2Zmc2V0KHN0YXJ0KTsKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBlbmRSZWdpb24gPSBnZXRSZWdpb25BdENoYXJhY3Rlck9mZnNldChzdGFydCArIGxlbmd0aCk7CgkJCXdoaWxlIChjdXJyZW50UmVnaW9uICE9IGVuZFJlZ2lvbiAmJiBjdXJyZW50UmVnaW9uICE9IG51bGwpIHsKCQkJCXJlc3VsdHMuYWRkKGN1cnJlbnRSZWdpb24pOwoJCQkJY3VycmVudFJlZ2lvbiA9IGN1cnJlbnRSZWdpb24uZ2V0TmV4dCgpOwoJCQl9CgkJCS8vIG5lZWQgdG8gYWRkIHRoYXQgbGFzdCBlbmQgcmVnaW9uCgkJCS8vIGNhbiBiZSBudWxsIGluIHRoZSBjYXNlIG9mIGFuIGVtcHR5IGRvY3VtZW50CgkJCWlmIChlbmRSZWdpb24gIT0gbnVsbCkKCQkJCXJlc3VsdHMuYWRkKGVuZFJlZ2lvbik7CgkJfQoJCWZpbmFsbHkgewoJCQlyZWxlYXNlTG9jaygpOwoJCX0KCQkvLyBlbmQgdGhyZWFkIHNhZmUgYmxvY2sKCgkJcmV0dXJuIChJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uW10pIHJlc3VsdHMudG9BcnJheShuZXcgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbltyZXN1bHRzLnNpemUoKV0pOwoJfQoKCS8qKgoJICogd2FzIG1hZGUgcHVibGljIGZvciBlYXNpZXIgdGVzdGluZy4gTm9ybWFsbHkgc2hvdWxkIG5ldmVyIGJlIHVzZWQgYnkKCSAqIGNsaWVudCBjb2Rlcy4KCSAqLwoJcHVibGljIElTdHJ1Y3R1cmVkVGV4dFJlUGFyc2VyIGdldFJlUGFyc2VyKCkgewoJCWlmIChmUmVQYXJzZXIgPT0gbnVsbCkgewoJCQlmUmVQYXJzZXIgPSBuZXcgU3RydWN0dXJlZERvY3VtZW50UmVQYXJzZXIoKTsKCQkJZlJlUGFyc2VyLnNldFN0cnVjdHVyZWREb2N1bWVudCh0aGlzKTsKCQl9CgkJcmV0dXJuIGZSZVBhcnNlcjsKCX0KCglwcml2YXRlIElUZXh0U3RvcmUgZ2V0U3RvcmUoKSB7CgkJQXNzZXJ0LmlzTm90TnVsbChmU3RvcmUpOwoJCXJldHVybiBmU3RvcmU7Cgl9CgoJcHVibGljIFN0cmluZyBnZXRUZXh0KCkgewoJCVN0cmluZyByZXN1bHQgPSBnZXQoKTsKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgZG9jdW1lbnQncyBsaW5lIHRyYWNrZXIuIEFzc3VtZXMgdGhhdCB0aGUgZG9jdW1lbnQgaGFzIGJlZW4KCSAqIGluaXRpYWxpemVkIHdpdGggYSBsaW5lIHRyYWNrZXIuCgkgKiAKCSAqIEByZXR1cm4gdGhlIGRvY3VtZW50J3MgbGluZSB0cmFja2VyCgkgKi8KCXByaXZhdGUgSUxpbmVUcmFja2VyIGdldFRyYWNrZXIoKSB7CgkJQXNzZXJ0LmlzTm90TnVsbChmVHJhY2tlcik7CgkJcmV0dXJuIGZUcmFja2VyOwoJfQoKCXB1YmxpYyBJU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlciBnZXRVbmRvTWFuYWdlcigpIHsKCQlpZiAoZlVuZG9NYW5hZ2VyID09IG51bGwpIHsKCQkJZlVuZG9NYW5hZ2VyID0gbmV3IFN0cnVjdHVyZWRUZXh0VW5kb01hbmFnZXIoKTsKCQl9CgkJcmV0dXJuIGZVbmRvTWFuYWdlcjsKCX0KCgl2b2lkIGluaXRpYWxpemVGaXJzdEFuZExhc3REb2N1bWVudFJlZ2lvbigpIHsKCQkvLyBjYWNoZWQgTm9kZSBtdXN0IGFsc28gYmUgZmlyc3QsIGF0IHRoZSBpbml0aWFsIHBvaW50LiBPbmx5CgkJLy8gdmFsaWQKCQkvLyB0byBjYWxsIHRoaXMgbWV0aG9kIHJpZ2h0IGFmdGVyIHRoZSBmaXJzdCBwYXJzZS4KCQkvLyAKCQkvLyB3aGVuIHN0YXJ0aW5nIGFmcmVzaCwgb3VyIGNhY2hlZE5vZGUgc2hvdWxkIGJlIG91ciBmaXJzdE5vZGUsCgkJLy8gc28gYmUgc3VyZSB0byBpbml0aWFsaXplIHRoZSBmaXJzdE5vZGUKCQlmaXJzdERvY3VtZW50UmVnaW9uID0gZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKTsKCQkvLyBiZSBzdXJlIHRvIHVzZSAnZ2V0TmV4dCcgZm9yIHRoaXMgaW5pdGlhbCBmaW5kaW5nIG9mIHRoZSBsYXN0CgkJLy8gbm9kZSwKCQkvLyBzaW5jZSB0aGUgaW1wbGVtZW50YXRpb24gb2Ygbm9kZS5nZXRMYXN0Tm9kZSBtYXkgc2ltcGx5IGNhbGwKCQkvLyBzdHJ1Y3R1cmVkRG9jdW1lbnQuZ2V0TGFzdFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiEKCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGFOb2RlID0gZmlyc3REb2N1bWVudFJlZ2lvbjsKCQlpZiAoYU5vZGUgPT0gbnVsbCkgewoJCQkvLyBkZWZlY3QgMjU0NjA3OiB0byBoYW5kbGUgZW1wdHkgZG9jdW1lbnRzIHJpZ2h0LCBpZgoJCQkvLyBmaXJzdG5vZGUgaXMKCQkJLy8gbnVsbCwgbWFrZSBzdXJlIGxhc3Qgbm9kZSBpcyBudWxsIHRvbwoJCQlsYXN0RG9jdW1lbnRSZWdpb24gPSBudWxsOwoJCX0KCQllbHNlIHsKCQkJd2hpbGUgKGFOb2RlICE9IG51bGwpIHsKCQkJCWxhc3REb2N1bWVudFJlZ2lvbiA9IGFOb2RlOwoJCQkJYU5vZGUgPSBhTm9kZS5nZXROZXh0KCk7CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNpbnNlcnRQb3NpdGlvblVwZGF0ZXIKCSAqLwoJcHVibGljIHZvaWQgaW5zZXJ0UG9zaXRpb25VcGRhdGVyKElQb3NpdGlvblVwZGF0ZXIgdXBkYXRlciwgaW50IGluZGV4KSB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkuaW5zZXJ0UG9zaXRpb25VcGRhdGVyKHVwZGF0ZXIsIGluZGV4KTsKCX0KCglwcml2YXRlIHZvaWQgaW50ZXJuYWxfYWRkUG9zaXRpb25DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnkpIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5hZGRQb3NpdGlvbkNhdGVnb3J5KGNhdGVnb3J5KTsKCX0KCglwcml2YXRlIHZvaWQgaW50ZXJuYWxfYWRkUG9zaXRpb25VcGRhdGVyKElQb3NpdGlvblVwZGF0ZXIgdXBkYXRlcikgewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLmFkZFBvc2l0aW9uVXBkYXRlcih1cGRhdGVyKTsKCX0KCglwcml2YXRlIHZvaWQgaW50ZXJuYWxfc2V0UGFyc2VyKFJlZ2lvblBhcnNlciBuZXdQYXJzZXIpIHsKCQlmUGFyc2VyID0gbmV3UGFyc2VyOwoJfQoKCVN0cmluZyBpbnRlcm5hbEdldChpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJU3RyaW5nIHJlc3VsdCA9IG51bGw7CgkJLy8gaW50IG15TGVuZ3RoID0gZ2V0TGVuZ3RoKCk7CgkJLy8gaWYgKCgwID4gb2Zmc2V0KSB8fCAoMCA+IGxlbmd0aCkgfHwgKG9mZnNldCArIGxlbmd0aCA+IG15TGVuZ3RoKSkKCQkvLyB0aHJvdyBuZXcgQmFkTG9jYXRpb25FeGNlcHRpb24oKTsKCQlyZXN1bHQgPSBnZXRTdG9yZSgpLmdldChvZmZzZXQsIGxlbmd0aCk7CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIEBwYXJhbSByZXF1ZXN0ZXIKCSAqIEBwYXJhbSBzdGFydAoJICogQHBhcmFtIHJlcGxhY2VtZW50TGVuZ3RoCgkgKiBAcGFyYW0gY2hhbmdlcwoJICogQHJldHVybgoJICovCglwcml2YXRlIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IGludGVybmFsUmVwbGFjZVRleHQoT2JqZWN0IHJlcXVlc3RlciwgaW50IHN0YXJ0LCBpbnQgcmVwbGFjZW1lbnRMZW5ndGgsIFN0cmluZyBjaGFuZ2VzLCBib29sZWFuIGlnbm9yZVJlYWRPbmx5U2V0dGluZ3MpIHsKCQlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCByZXN1bHQgPSBudWxsOwoKCQlzdG9wUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCQlpZiAoY2hhbmdlcyA9PSBudWxsKQoJCQljaGFuZ2VzID0gIiI7IC8vJE5PTi1OTFMtMSQKCQkvLyAKCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpCgkJCVN5c3RlbS5vdXQucHJpbnRsbihnZXRDbGFzcygpLmdldE5hbWUoKSArICI6OnJlcGxhY2VUZXh0KCIgKyBzdGFydCArICIsIiArIHJlcGxhY2VtZW50TGVuZ3RoICsgIiwiICsgY2hhbmdlcyArICIpIik7IC8vJE5PTi1OTFMtNCQvLyROT04tTkxTLTMkLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQlpZiAoRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRPbmx5IHx8IERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0UmF3U3RydWN0dXJlZERvY3VtZW50T25seSkgewoJCQlzdGFydFN0cmVhbVRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQl9CgkJdHJ5IHsKCQkJLy8gTm90ZTogZXZlbnQgbXVzdCBiZSBjb21wdXRlZCBiZWZvcmUgJ2ZpcmUnIG1ldGhvZCBjYWxsZWQKCQkJZkRvY3VtZW50RXZlbnQgPSBuZXcgRG9jdW1lbnRFdmVudCh0aGlzLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgsIGNoYW5nZXMpOwoJCQlmaXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlZCgpOwoKCQkJdHJ5IHsKCQkJCWFjcXVpcmVMb2NrKCk7CgoJCQkJaWYgKCFpZ25vcmVSZWFkT25seVNldHRpbmdzICYmIChjb250YWluc1JlYWRPbmx5KHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCkpKSB7CgkJCQkJTm9DaGFuZ2VFdmVudCBub0NoYW5nZUV2ZW50ID0gbmV3IE5vQ2hhbmdlRXZlbnQodGhpcywgcmVxdWVzdGVyLCBjaGFuZ2VzLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgpOwoJCQkJCW5vQ2hhbmdlRXZlbnQucmVhc29uID0gTm9DaGFuZ2VFdmVudC5SRUFEX09OTFlfU1RBVEVfQ0hBTkdFOwoJCQkJCXJlc3VsdCA9IG5vQ2hhbmdlRXZlbnQ7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlyZXN1bHQgPSB1cGRhdGVNb2RlbChyZXF1ZXN0ZXIsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCwgY2hhbmdlcyk7CgkJCQl9CgkJCX0KCQkJZmluYWxseSB7CgkJCQlyZWxlYXNlTG9jaygpOwoJCQl9CgoKCQkJaWYgKERlYnVnLnBlcmZUZXN0UmF3U3RydWN0dXJlZERvY3VtZW50T25seSB8fCBEZWJ1Zy5wZXJmVGVzdCkgewoJCQkJbG9uZyBzdG9wU3RyZWFtVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IFRpbWUgZm9yIElTdHJ1Y3R1cmVkRG9jdW1lbnQgcmF3IHJlcGxhY2VUZXh0OiAiICsgKHN0b3BTdHJlYW1UaW1lIC0gc3RhcnRTdHJlYW1UaW1lKSk7IC8vJE5PTi1OTFMtMSQKCQkJfQoJCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpIHsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiZXZlbnQgdHlwZSByZXR1cm5lZCBieSByZXBsYWNlVGV4dFdpdGhOb0RlYnVnZ2luZ1RocmVhZDogIiArIHJlc3VsdCk7IC8vJE5PTi1OTFMtMSQKCQkJfQoJCX0KCQlmaW5hbGx5IHsKCQkJLy8gRlVUVVJFX1RPX0RPOiBpbXBsZW1lbnQgY2FsbGJhY2sgbWVjaGFuaXNtPyB0byBhdm9pZCBpbnN0YW5jZW9mCgkJCS8vIGFuZCBjYXN0aW5nCgkJCS8vIGZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCBtdXN0IGJlIGNhbGxlZCBpbiBvcmRlciB0byBlbmQKCQkJLy8gZG9jdW1lbnRBYm91dFRvQmVDaGFuZ2VkIHN0YXRlCgoJCQkvLyBpbmNyZW1lbnQgbW9kaWZpY2F0aW9uIHN0YW1wIGlmIG1vZGlmaWNhdGlvbnMgd2VyZSBtYWRlCgkJCWlmIChyZXN1bHQgIT0gbnVsbCAmJiAhKHJlc3VsdCBpbnN0YW5jZW9mIE5vQ2hhbmdlRXZlbnQpKQoJCQkJZk1vZGlmaWNhdGlvblN0YW1wKys7CgoJCQlpZiAocmVzdWx0ID09IG51bGwpIHsKCQkJCS8vIHJlc3VsdCBzaG91bGQgbm90IGJlIG51bGwsIGJ1dCBpZiBhbiBleGNlcHRpb24gd2FzIHRocm93biwKCQkJCS8vIGl0IHdpbGwgYmUKCQkJCS8vIHNvIHNlbmQgYSBub0NoYW5nZUV2ZW50IGFuZCBsb2cgdGhlIHByb2JsZW0KCQkJCU5vQ2hhbmdlRXZlbnQgbm9DaGFuZ2VFdmVudCA9IG5ldyBOb0NoYW5nZUV2ZW50KHRoaXMsIHJlcXVlc3RlciwgY2hhbmdlcywgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoKTsKCQkJCW5vQ2hhbmdlRXZlbnQucmVhc29uID0gTm9DaGFuZ2VFdmVudC5OT19FVkVOVDsKCQkJCWZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChub0NoYW5nZUV2ZW50KTsKCQkJCUxvZ2dlci5sb2coTG9nZ2VyLkVSUk9SLCAiUHJvZ3JhbSBFcnJvcjogaW52YWxpZCBzdHJ1Y3R1cmVkIGRvY3VtZW50IGV2ZW50Iik7IC8vJE5PTi1OTFMtMSQKCQkJfQoJCQllbHNlIHsKCQkJCWlmIChyZXN1bHQgaW5zdGFuY2VvZiBSZWdpb25DaGFuZ2VkRXZlbnQpIHsKCQkJCQlmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoKFJlZ2lvbkNoYW5nZWRFdmVudCkgcmVzdWx0KTsKCQkJCX0KCQkJCWVsc2UgewoJCQkJCWlmIChyZXN1bHQgaW5zdGFuY2VvZiBSZWdpb25zUmVwbGFjZWRFdmVudCkgewoJCQkJCQlmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoKFJlZ2lvbnNSZXBsYWNlZEV2ZW50KSByZXN1bHQpOwoJCQkJCX0KCQkJCQllbHNlIHsKCQkJCQkJaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50KSB7CgkJCQkJCQkvLyBwcm9iYWJseSBtb3JlIGVmZmljaWVudCB0byBtYXJrIG9sZCByZWdpb25zIGFzCgkJCQkJCQkvLyAnZGVsZXRlZCcgYXQgdGhlIHRpbWUKCQkJCQkJCS8vIHRoYXQgYXJlIGRldGVybWluZWQgdG8gYmUgZGVsZXRlZCwgYnV0IEknbGwgZG8KCQkJCQkJCS8vIGhlcmUKCQkJCQkJCS8vIGluIHRoZW4gY2VudHJhbCBzcG90CgkJCQkJCQkvLyBmb3IgcHJvZ3JhbW1pbmcgZWFzZS4KCQkJCQkJCXVwZGF0ZURlbGV0ZWRGaWVsZHMoKFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50KSByZXN1bHQpOwoJCQkJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KChTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCkgcmVzdWx0KTsKCQkJCQkJfQoJCQkJCQllbHNlIHsKCQkJCQkJCWlmIChyZXN1bHQgaW5zdGFuY2VvZiBOb0NoYW5nZUV2ZW50KSB7CgkJCQkJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KChOb0NoYW5nZUV2ZW50KSByZXN1bHQpOwoJCQkJCQkJfQoJCQkJCQkJZWxzZSB7CgkJCQkJCQkJLy8gaWYgaGVyZSwgdGhpcyBtZWFucyBhIG5ldyBldmVudCB3YXMgY3JlYXRlZAoJCQkJCQkJCS8vIGFuZCBub3QgaGFuZGxlZCBoZXJlCgkJCQkJCQkJLy8ganVzdCBzZW5kIGEgbm8gZXZlbnQgdW50aWwgdGhpcyBpc3N1ZSBpcwoJCQkJCQkJCS8vIHJlc29sdmVkLgoJCQkJCQkJCU5vQ2hhbmdlRXZlbnQgbm9DaGFuZ2VFdmVudCA9IG5ldyBOb0NoYW5nZUV2ZW50KHRoaXMsIHJlcXVlc3RlciwgY2hhbmdlcywgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoKTsKCQkJCQkJCQlub0NoYW5nZUV2ZW50LnJlYXNvbiA9IE5vQ2hhbmdlRXZlbnQuTk9fRVZFTlQ7CgkJCQkJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KG5vQ2hhbmdlRXZlbnQpOwoJCQkJCQkJCUxvZ2dlci5sb2coTG9nZ2VyLklORk8sICJQcm9ncmFtIEVycm9yOiB1bmV4cGVjdGVkIHN0cnVjdHVyZWQgZG9jdW1lbnQgZXZlbnQ6ICIgKyByZXN1bHQpOyAvLyROT04tTkxTLTEkCgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50T25seSkgewoJCQkJbG9uZyBzdG9wU3RyZWFtVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IFRvdGFsIFRpbWUgZm9yIElTdHJ1Y3R1cmVkRG9jdW1lbnQgZXZlbnQgc2lnbmFsaW5nL3Byb2Nlc3NpbmcgaW4gcmVwbGFjZVRleHQ6ICIgKyAoc3RvcFN0cmVhbVRpbWUgLSBzdGFydFN0cmVhbVRpbWUpKTsgLy8kTk9OLU5MUy0xJAoJCQl9CgkJCXJlc3VtZVBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCk7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBqYXZhLmxhbmcuQ2hhclNlcXVlbmNlI2xlbmd0aCgpCgkgKi8KCXB1YmxpYyBpbnQgbGVuZ3RoKCkgewoKCQlyZXR1cm4gZ2V0TGVuZ3RoKCk7Cgl9CgkKCXB1YmxpYyB2b2lkIG1ha2VSZWFkT25seShpbnQgc3RhcnRPZmZzZXQsIGludCBsZW5ndGgpIHsKCQltYWtlUmVhZE9ubHkoc3RhcnRPZmZzZXQsIGxlbmd0aCwgZmFsc2UsIGZhbHNlKTsKCX0KCglwdWJsaWMgdm9pZCBtYWtlUmVhZE9ubHkoaW50IHN0YXJ0T2Zmc2V0LCBpbnQgbGVuZ3RoLCBib29sZWFuIGNhbkluc2VydEJlZm9yZSwgYm9vbGVhbiBjYW5JbnNlcnRBZnRlcikgewkKCQkvLyBkb2Vzbid0IG1ha2Ugc2Vuc2UgdG8gaGF2ZSBhIHJlYWRvbmx5IHJlZ2lvbiBvZiAwIGxlbmd0aCwKCQkvLyBzbyB3ZSdsbCBpZ25vcmUgdGhvc2UgcmVxdWVzdHMKCQlpZiAobGVuZ3RoIDw9IDApCgkJCXJldHVybjsKCQlTdHJpbmcgYWZmZWN0ZWRUZXh0ID0gdGhpcy5nZXQoc3RhcnRPZmZzZXQsIGxlbmd0aCk7CgkJLy8gYSBkb2N1bWVudCBldmVudCBmb3IgInJlYWQgb25seSIgY2hhbmdlIC4uLiBtdXN0CgkJLy8gYmUgZm9sbG93ZWQgYnkgIm5vIGNoYW5nZSIgc3RydWN0dXJlZERvY3VtZW50IGV2ZW50CgkJLy8gZkRvY3VtZW50RXZlbnQgPSBuZXcgRG9jdW1lbnRFdmVudCh0aGlzLCBzdGFydE9mZnNldCwgbGVuZ3RoLAoJCS8vIGFmZmVjdGVkVGV4dCk7CgkJZmlyZVJlYWRPbmx5QWJvdXRUb0JlQ2hhbmdlZCgpOwoJCS8vIGlmIChjb250YWluc1JlYWRPbmx5KHN0YXJ0T2Zmc2V0LCBsZW5ndGgpKSB7CgkJLy8gYWRqdXN0UmVhZE9ubHlSZWdpb25zKHN0YXJ0T2Zmc2V0LCBsZW5ndGgpOwoJCS8vIH0gZWxzZSB7CgkJLy8gd2UgY2FuIGJsaW5kbHkgYWRkIGNhdGVnb3J5LCBzaW5jZSBubyBoYXJtIGRvbmUgaWYgYWxyZWFkeQoJCS8vIGV4aXN0cy4KCQlhZGRQb3NpdGlvbkNhdGVnb3J5KFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZKTsKCQlQb3NpdGlvbiBuZXdQb3NpdGlvbiA9IG5ldyBSZWFkT25seVBvc2l0aW9uKHN0YXJ0T2Zmc2V0LCBsZW5ndGgsIGNhbkluc2VydEJlZm9yZSk7CgkJdHJ5IHsKCQkJYWRkUG9zaXRpb24oUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlksIG5ld1Bvc2l0aW9uKTsKCQkJLy8gRklYTUU6IG5lZWQgdG8gY2hhbmdlIEFQSSB0byBwYXNzIGluIHJlcXVlc3Rlciwgc28gdGhpcyBldmVudAoJCQkvLyBjYW4gYmUKCQkJLy8gY3JlYXRlZCBjb3JyZWN0bHksIGluc3RlYWQgb2YgdXNpbmcgbnVsbC4KCQkJTm9DaGFuZ2VFdmVudCBub0NoYW5nZUV2ZW50ID0gbmV3IE5vQ2hhbmdlRXZlbnQodGhpcywgbnVsbCwgYWZmZWN0ZWRUZXh0LCBzdGFydE9mZnNldCwgbGVuZ3RoKTsKCQkJbm9DaGFuZ2VFdmVudC5yZWFzb24gPSBOb0NoYW5nZUV2ZW50LlJFQURfT05MWV9TVEFURV9DSEFOR0U7CgkJCWZpcmVSZWFkT25seVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KG5vQ2hhbmdlRXZlbnQpOwoJCX0KCQljYXRjaCAoQmFkTG9jYXRpb25FeGNlcHRpb24gZSkgewoJCQkvLyBmb3Igbm93LCBsb2cgYW5kIGlnbm9yZS4gUGVyaGFwcyBsYXRlciB3ZQoJCQkvLyBjb3VsZCBhZGp1c3QgdG8gaGFuZGxlIHNvbWUgY2FzZXM/CgkJCUxvZ2dlci5sb2dFeGNlcHRpb24oKCJjb3VsZCBub3QgY3JlYXRlIHJlYWRvbmx5IHJlZ2lvbiBhdCAiICsgc3RhcnRPZmZzZXQgKyAiIHRvICIgKyBsZW5ndGgpLCBlKTsgLy8kTk9OLU5MUy0xJCAvLyROT04tTkxTLTIkCgkJfQoJCWNhdGNoIChCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIGUpIHsKCQkJLy8gc2hvdWxkIG5ldmVyIG9jY3VyLCBzaW5jZSB3ZSBhZGQgY2F0ZWdvcnkKCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihlKTsKCQl9Cgl9CgoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnQgbmV3SW5zdGFuY2UoKSB7CgkJSVN0cnVjdHVyZWREb2N1bWVudCBuZXdJbnN0YW5jZSA9IFN0cnVjdHVyZWREb2N1bWVudEZhY3RvcnkuZ2V0TmV3U3RydWN0dXJlZERvY3VtZW50SW5zdGFuY2UoZ2V0UGFyc2VyKCkubmV3SW5zdGFuY2UoKSk7CgkJKChCYXNpY1N0cnVjdHVyZWREb2N1bWVudCkgbmV3SW5zdGFuY2UpLnNldFJlUGFyc2VyKGdldFJlUGFyc2VyKCkubmV3SW5zdGFuY2UoKSk7CgkJaWYgKGdldERvY3VtZW50UGFydGl0aW9uZXIoKSBpbnN0YW5jZW9mIFN0cnVjdHVyZWRUZXh0UGFydGl0aW9uZXIpIHsKCQkJbmV3SW5zdGFuY2Uuc2V0RG9jdW1lbnRQYXJ0aXRpb25lcigoKFN0cnVjdHVyZWRUZXh0UGFydGl0aW9uZXIpIGdldERvY3VtZW50UGFydGl0aW9uZXIoKSkubmV3SW5zdGFuY2UoKSk7CgkJCW5ld0luc3RhbmNlLmdldERvY3VtZW50UGFydGl0aW9uZXIoKS5jb25uZWN0KG5ld0luc3RhbmNlKTsKCQl9CgkJbmV3SW5zdGFuY2Uuc2V0TGluZURlbGltaXRlcihnZXRMaW5lRGVsaW1pdGVyKCkpOwoJCWlmIChnZXRFbmNvZGluZ01lbWVudG8oKSAhPSBudWxsKSB7CgkJCW5ld0luc3RhbmNlLnNldEVuY29kaW5nTWVtZW50bygoRW5jb2RpbmdNZW1lbnRvKSBnZXRFbmNvZGluZ01lbWVudG8oKS5jbG9uZSgpKTsKCQl9CgkJcmV0dXJuIG5ld0luc3RhbmNlOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnRleHQuSVJlZ2lvbkNvbXBhcmlibGUjcmVnaW9uTWF0Y2hlcyhpbnQsCgkgKiAgICAgIGludCwgamF2YS5sYW5nLlN0cmluZykKCSAqLwoJcHVibGljIGJvb2xlYW4gcmVnaW9uTWF0Y2hlcyhpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoLCBTdHJpbmcgc3RyaW5nVG9Db21wYXJlKSB7CgkJYm9vbGVhbiByZXN1bHQgPSBmYWxzZTsKCQlJVGV4dFN0b3JlIHN0b3JlID0gZ2V0U3RvcmUoKTsKCQlpZiAoc3RvcmUgaW5zdGFuY2VvZiBJUmVnaW9uQ29tcGFyaWJsZSkgewoJCQlyZXN1bHQgPSAoKElSZWdpb25Db21wYXJpYmxlKSBzdG9yZSkucmVnaW9uTWF0Y2hlcyhvZmZzZXQsIGxlbmd0aCwgc3RyaW5nVG9Db21wYXJlKTsKCQl9CgkJZWxzZSB7CgkJCXJlc3VsdCA9IGdldChvZmZzZXQsIGxlbmd0aCkuZXF1YWxzKHN0cmluZ1RvQ29tcGFyZSk7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJcHVibGljIGJvb2xlYW4gcmVnaW9uTWF0Y2hlc0lnbm9yZUNhc2UoaW50IG9mZnNldCwgaW50IGxlbmd0aCwgU3RyaW5nIHN0cmluZ1RvQ29tcGFyZSkgewoJCWJvb2xlYW4gcmVzdWx0ID0gZmFsc2U7CgkJSVRleHRTdG9yZSBzdG9yZSA9IGdldFN0b3JlKCk7CgkJaWYgKHN0b3JlIGluc3RhbmNlb2YgSVJlZ2lvbkNvbXBhcmlibGUpIHsKCQkJcmVzdWx0ID0gKChJUmVnaW9uQ29tcGFyaWJsZSkgc3RvcmUpLnJlZ2lvbk1hdGNoZXNJZ25vcmVDYXNlKG9mZnNldCwgbGVuZ3RoLCBzdHJpbmdUb0NvbXBhcmUpOwoJCX0KCQllbHNlIHsKCQkJcmVzdWx0ID0gZ2V0KG9mZnNldCwgbGVuZ3RoKS5lcXVhbHNJZ25vcmVDYXNlKHN0cmluZ1RvQ29tcGFyZSk7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbiNyZWdpc3RlclBvc3ROb3RpZmljYXRpb25SZXBsYWNlKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50TGlzdGVuZXIsCgkgKiAgICAgIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uLklSZXBsYWNlKQoJICovCglwdWJsaWMgdm9pZCByZWdpc3RlclBvc3ROb3RpZmljYXRpb25SZXBsYWNlKElEb2N1bWVudExpc3RlbmVyIG93bmVyLCBJRG9jdW1lbnRFeHRlbnNpb24uSVJlcGxhY2UgcmVwbGFjZSkgewoJCWlmIChmQWNjZXB0UG9zdE5vdGlmaWNhdGlvblJlcGxhY2VzKSB7CgkJCWlmIChmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMgPT0gbnVsbCkKCQkJCWZQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlcyA9IG5ldyBBcnJheUxpc3QoMSk7CgkJCWZQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlcy5hZGQobmV3IFJlZ2lzdGVyZWRSZXBsYWNlKG93bmVyLCByZXBsYWNlKSk7CgkJfQoJfQoKCXByb3RlY3RlZCB2b2lkIHJlbGVhc2VMb2NrKCkgewoJCS8vIGRvIG5vdGhpbmcgaGVyZSBpbiBzdXBlciBjbGFzcwoJfQoKCXB1YmxpYyB2b2lkIHJlbW92ZURvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVyKElNb2RlbEFib3V0VG9CZUNoYW5nZWRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzICE9IG51bGwpICYmIChsaXN0ZW5lciAhPSBudWxsKSkgewoJCQkJLy8gaWYgaXRzIG5vdCBpbiB0aGUgbGlzdGVuZXJzLCB3ZSdsbCBpZ25vcmUgdGhlIHJlcXVlc3QKCQkJCWlmIChVdGlsaXRpZXMuY29udGFpbnMoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJCWludCBvbGRTaXplID0gZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSAtIDE7CgkJCQkJT2JqZWN0W10gbmV3TGlzdGVuZXJzID0gbmV3IE9iamVjdFtuZXdTaXplXTsKCQkJCQlpbnQgaW5kZXggPSAwOwoJCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgb2xkU2l6ZTsgaSsrKSB7CgkJCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVyc1tpXSA9PSBsaXN0ZW5lcikgeyAvLyBpZ25vcmUKCQkJCQkJfQoJCQkJCQllbHNlIHsKCQkJCQkJCS8vIGNvcHkgb2xkIHRvIG5ldyBpZiBpdHMgbm90IHRoZSBvbmUgd2UgYXJlCgkJCQkJCQkvLyByZW1vdmluZwoJCQkJCQkJbmV3TGlzdGVuZXJzW2luZGV4KytdID0gZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnNbaV07CgkJCQkJCX0KCQkJCQl9CgkJCQkJLy8gbm93IHRoYXQgd2UgaGF2ZSBhIG5ldyBhcnJheSwgbGV0J3Mgc3dpdGNoIGl0IGZvciB0aGUKCQkJCQkvLyBvbGQKCQkJCQkvLyBvbmUKCQkJCQlmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJCX0KCQkJfQoJCX0KCX0KCgkvKioKCSAqIHJlbW92ZU1vZGVsQ2hhbmdlZExpc3RlbmVyIG1ldGhvZCBjb21tZW50LgoJICovCglwdWJsaWMgdm9pZCByZW1vdmVEb2N1bWVudENoYW5nZWRMaXN0ZW5lcihJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycyAhPSBudWxsKSAmJiAobGlzdGVuZXIgIT0gbnVsbCkpIHsKCQkJCS8vIGlmIGl0cyBub3QgaW4gdGhlIGxpc3RlbmVycywgd2UnbGwgaWdub3JlIHRoZSByZXF1ZXN0CgkJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCQlpbnQgb2xkU2l6ZSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLmxlbmd0aDsKCQkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgLSAxOwoJCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQkJaW50IGluZGV4ID0gMDsKCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFNpemU7IGkrKykgewoJCQkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnNbaV0gPT0gbGlzdGVuZXIpIHsgLy8gaWdub3JlCgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQkvLyBjb3B5IG9sZCB0byBuZXcgaWYgaXRzIG5vdCB0aGUgb25lIHdlIGFyZQoJCQkJCQkJLy8gcmVtb3ZpbmcKCQkJCQkJCW5ld0xpc3RlbmVyc1tpbmRleCsrXSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzW2ldOwoJCQkJCQl9CgkJCQkJfQoJCQkJCS8vIG5vdyB0aGF0IHdlIGhhdmUgYSBuZXcgYXJyYXksIGxldCdzIHN3aXRjaCBpdCBmb3IgdGhlCgkJCQkJLy8gb2xkCgkJCQkJLy8gb25lCgkJCQkJZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVyKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycyAhPSBudWxsKSAmJiAobGlzdGVuZXIgIT0gbnVsbCkpIHsKCQkJCS8vIGlmIGl0cyBub3QgaW4gdGhlIGxpc3RlbmVycywgd2UnbGwgaWdub3JlIHRoZSByZXF1ZXN0CgkJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQkJaW50IG9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSAtIDE7CgkJCQkJT2JqZWN0W10gbmV3TGlzdGVuZXJzID0gbmV3IE9iamVjdFtuZXdTaXplXTsKCQkJCQlpbnQgaW5kZXggPSAwOwoJCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgb2xkU2l6ZTsgaSsrKSB7CgkJCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnNbaV0gPT0gbGlzdGVuZXIpIHsgLy8gaWdub3JlCgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQkvLyBjb3B5IG9sZCB0byBuZXcgaWYgaXRzIG5vdCB0aGUgb25lIHdlIGFyZQoJCQkJCQkJLy8gcmVtb3ZpbmcKCQkJCQkJCW5ld0xpc3RlbmVyc1tpbmRleCsrXSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVyc1tpXTsKCQkJCQkJfQoJCQkJCX0KCQkJCQkvLyBub3cgdGhhdCB3ZSBoYXZlIGEgbmV3IGFycmF5LCBsZXQncyBzd2l0Y2ggaXQgZm9yIHRoZQoJCQkJCS8vIG9sZAoJCQkJCS8vIG9uZQoJCQkJCWZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJCX0KCQkJfQoJCX0KCX0KCglwdWJsaWMgdm9pZCByZW1vdmVEb2N1bWVudExpc3RlbmVyKElEb2N1bWVudExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmICgoZkRvY3VtZW50TGlzdGVuZXJzICE9IG51bGwpICYmIChsaXN0ZW5lciAhPSBudWxsKSkgewoJCQkJLy8gaWYgaXRzIG5vdCBpbiB0aGUgbGlzdGVuZXJzLCB3ZSdsbCBpZ25vcmUgdGhlIHJlcXVlc3QKCQkJCWlmIChVdGlsaXRpZXMuY29udGFpbnMoZkRvY3VtZW50TGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCQlpbnQgb2xkU2l6ZSA9IGZEb2N1bWVudExpc3RlbmVycy5sZW5ndGg7CgkJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplIC0gMTsKCQkJCQlJRG9jdW1lbnRMaXN0ZW5lcltdIG5ld0xpc3RlbmVycyA9IG5ldyBJRG9jdW1lbnRMaXN0ZW5lcltuZXdTaXplXTsKCQkJCQlpbnQgaW5kZXggPSAwOwoJCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgb2xkU2l6ZTsgaSsrKSB7CgkJCQkJCWlmIChmRG9jdW1lbnRMaXN0ZW5lcnNbaV0gPT0gbGlzdGVuZXIpIHsgLy8gaWdub3JlCgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQkvLyBjb3B5IG9sZCB0byBuZXcgaWYgaXRzIG5vdCB0aGUgb25lIHdlIGFyZQoJCQkJCQkJLy8gcmVtb3ZpbmcKCQkJCQkJCW5ld0xpc3RlbmVyc1tpbmRleCsrXSA9IGZEb2N1bWVudExpc3RlbmVyc1tpXTsKCQkJCQkJfQoJCQkJCX0KCQkJCQkvLyBub3cgdGhhdCB3ZSBoYXZlIGEgbmV3IGFycmF5LCBsZXQncyBzd2l0Y2ggaXQgZm9yIHRoZQoJCQkJCS8vIG9sZAoJCQkJCS8vIG9uZQoJCQkJCWZEb2N1bWVudExpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJCX0KCQkJfQoJCX0KCX0KCgkvKgoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudCNyZW1vdmVEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIpCgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIoSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJQXNzZXJ0LmlzTm90TnVsbChsaXN0ZW5lcik7CgkJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMgIT0gbnVsbCkKCQkJCWZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycy5yZW1vdmUobGlzdGVuZXIpOwoJCX0KCX0KCgkvKioKCSAqIFJlbW92ZXMgdGhlIGdpdmVuIDxjb2RlPlBvc2l0aW9uPC9jb2RlPiBmcm9tIHRoZSBkb2N1bWVudCdzIGRlZmF1bHQKCSAqIHBvc2l0aW9uIGNhdGVnb3J5LiBUaGUgZGVmYXVsdCBwb3NpdGlvbiBjYXRlZ29yeSBpcyB0byBiZSBkZWZpbmVkIGJ5CgkgKiB0aGUgaW1wbGVtZW50ZXJzLiBJZiB0aGUgcG9zaXRpb24gaXMgbm90IHBhcnQgb2YgdGhlIGRvY3VtZW50J3MgZGVmYXVsdAoJICogY2F0ZWdvcnkgbm90aGluZyBoYXBwZW5zLgoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQb3NpdGlvbihQb3NpdGlvbiBwb3NpdGlvbikgewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLnJlbW92ZVBvc2l0aW9uKHBvc2l0aW9uKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3JlbW92ZVBvc2l0aW9uCgkgKiBAZXhjZXB0aW9uIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHRoZSBjYXRlZ29yeSBpcyBub3QgZGVmaW5lZCBmb3IgdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZVBvc2l0aW9uKFN0cmluZyBjYXRlZ29yeSwgUG9zaXRpb24gcG9zaXRpb24pIHRocm93cyBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5yZW1vdmVQb3NpdGlvbihjYXRlZ29yeSwgcG9zaXRpb24pOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjcmVtb3ZlUG9zaXRpb25DYXRlZ29yeQoJICogQGV4Y2VwdGlvbiBCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiB0aGUgY2F0ZWdvcnkgaXMgbm90IGRlZmluZWQgZm9yIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQb3NpdGlvbkNhdGVnb3J5KFN0cmluZyBjYXRlZ29yeSkgdGhyb3dzIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLnJlbW92ZVBvc2l0aW9uQ2F0ZWdvcnkoY2F0ZWdvcnkpOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjcmVtb3ZlUG9zaXRpb25VcGRhdGVyCgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZVBvc2l0aW9uVXBkYXRlcihJUG9zaXRpb25VcGRhdGVyIHVwZGF0ZXIpIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5yZW1vdmVQb3NpdGlvblVwZGF0ZXIodXBkYXRlcik7Cgl9CgoJLyoqCgkgKiBSZW1vdmVzIHRoZSBnaXZlbiBkb2N1bWVudCBsaXN0ZW5lciBmcm9tIHRlaCBkb2N1bWVudCdzIGxpc3Qgb2YKCSAqIHByZW5vdGlmaWVkIGRvY3VtZW50IGxpc3RlbmVycy4gSWYgdGhlIGxpc3RlbmVyIGlzIG5vdCByZWdpc3RlcmVkIHdpdGgKCSAqIHRoZSBkb2N1bWVudCBub3RoaW5nIGhhcHBlbnMuCgkgKiA8cD4KCSAqIAoJICogVGhpcyBtZXRob2QgaXMgbm90IGZvciBwdWJsaWMgdXNlLCBpdCBtYXkgb25seSBiZSBjYWxsZWQgYnkKCSAqIGltcGxlbWVudGVycyBvZiA8Y29kZT5JRG9jdW1lbnRBZGFwdGVyPC9jb2RlPiBhbmQgb25seSBpZiB0aG9zZQoJICogaW1wbGVtZW50ZXJzIG5lZWQgdG8gaW1wbGVtZW50IDxjb2RlPklEb2N1bWVudExpc3RlbmVyPC9jb2RlPi4KCSAqIAoJICogQHBhcmFtIGRvY3VtZW50QWRhcHRlcgoJICogICAgICAgICAgICB0aGUgbGlzdGVuZXIgdG8gYmUgcmVtb3ZlZAoJICogCgkgKiBAc2VlICNhZGRQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXIoSURvY3VtZW50TGlzdGVuZXIpCgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZVByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcihvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudExpc3RlbmVyIGRvY3VtZW50QWRhcHRlcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLCBkb2N1bWVudEFkYXB0ZXIpKSB7CgkJCQlpbnQgcHJldmlvdXNTaXplID0gZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJaWYgKHByZXZpb3VzU2l6ZSA+IDEpIHsKCQkJCQlJRG9jdW1lbnRMaXN0ZW5lcltdIGxpc3RlbmVycyA9IG5ldyBJRG9jdW1lbnRMaXN0ZW5lcltwcmV2aW91c1NpemUgLSAxXTsKCQkJCQlpbnQgcHJldmlvdXNJbmRleCA9IDA7CgkJCQkJaW50IG5ld0luZGV4ID0gMDsKCQkJCQl3aGlsZSAocHJldmlvdXNJbmRleCA8IHByZXZpb3VzU2l6ZSkgewoJCQkJCQlpZiAoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnNbcHJldmlvdXNJbmRleF0gIT0gZG9jdW1lbnRBZGFwdGVyKQoJCQkJCQkJbGlzdGVuZXJzW25ld0luZGV4KytdID0gZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnNbcHJldmlvdXNJbmRleF07CgkJCQkJCXByZXZpb3VzSW5kZXgrKzsKCQkJCQl9CgkJCQkJZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycyA9IG51bGw7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJLyoqCgkgKiBUaGlzIG1ldGhvZCBpcyBmb3IgSU5URVJOQUwgVVNFIE9OTFkgYW5kIGlzIE5PVCBBUEkuCgkgKiAKCSAqIFJlYnVpbGRzIHRoZSBTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gY2hhaW4gZnJvbSB0aGUgZXhpc3RpbmcgdGV4dC4KCSAqIEZpbGVCdWZmZXIgc3VwcG9ydCBkb2VzIG5vdCBhbGxvdyBjbGllbnRzIHRvIGtub3cgdGhlIGRvY3VtZW50J3MKCSAqIGxvY2F0aW9uIGJlZm9yZSB0aGUgdGV4dCBjb250ZW50cyBhcmUgc2V0LgoJICogCgkgKiBAc2VlIHNldChTdHJpbmcpCgkgKi8KCXB1YmxpYyB2b2lkIHJlcGFyc2UoT2JqZWN0IHJlcXVlc3RlcikgewoJCXN0b3BQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJCWNsZWFyUmVhZE9ubHkoKTsKCgkJYWNxdWlyZUxvY2soKTsKCQl0cnkgewoJCQlDaGFyU2VxdWVuY2VSZWFkZXIgc3ViU2V0VGV4dFN0b3JlUmVhZGVyID0gbmV3IENoYXJTZXF1ZW5jZVJlYWRlcigoQ2hhclNlcXVlbmNlKSBnZXRTdG9yZSgpLCAwLCBnZXRTdG9yZSgpLmdldExlbmd0aCgpKTsKCQkJcmVzZXRQYXJzZXIoc3ViU2V0VGV4dFN0b3JlUmVhZGVyLCAwKTsKCQkJLy8KCQkJc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oZ2V0UGFyc2VyKCkuZ2V0RG9jdW1lbnRSZWdpb25zKCkpOwoJCQkvLyB3aGVuIHN0YXJ0aW5nIGFmcmVzaCwgb3VyIGNhY2hlZE5vZGUgc2hvdWxkIGJlIG91ciBmaXJzdE5vZGUsCgkJCS8vIHNvIGJlIHN1cmUgdG8gaW5pdGlhbGl6ZSB0aGUgZmlyc3ROb2RlIGFuZCBsYXN0Tm9kZQoJCQlpbml0aWFsaXplRmlyc3RBbmRMYXN0RG9jdW1lbnRSZWdpb24oKTsKCQkJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uSXRlcmF0b3Iuc2V0UGFyZW50RG9jdW1lbnQoZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKSwgdGhpcyk7CgkJfQoJCWZpbmFsbHkgewoJCQlyZWxlYXNlTG9jaygpOwoJCX0KCgkJcmVzdW1lUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3JlcGxhY2UKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHBvc2l0aW9uIGlzIG5vdCBhIHZhbGlkIHJhbmdlIGluIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgdm9pZCByZXBsYWNlKGludCBwb3MsIGludCBsZW5ndGgsIFN0cmluZyBzdHJpbmcpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJaWYgKERlYnVnLmRpc3BsYXlXYXJuaW5ncykgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIk5vdGU6IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OnJlcGxhY2UoaW50LCBpbnQsIFN0cmluZykgLi4uLiBpdHMgYmV0dGVyIHRvIHVzZSByZXBsYWNlVGV4dChzb3VyY2UsIHN0cmluZywgaW50LCBpbnQpIEFQSSBmb3Igc3RydWN0dXJlZERvY3VtZW50IHVwZGF0ZXMiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCQlyZXBsYWNlVGV4dCh0aGlzLCBwb3MsIGxlbmd0aCwgc3RyaW5nKTsKCX0KCgkvKioKCSAqIFJlcGxhY2UgdGhlIHRleHQgd2l0aCAibmV3VGV4dCIgc3RhcnRpbmcgYXQgcG9zaXRpb24gInN0YXJ0IiBmb3IgYQoJICogbGVuZ3RoIG9mICJyZXBsYWNlTGVuZ3RoIi4KCSAqIDxwPgoJICogCgkgKiBAcGFyYW0gc3RhcnQKCSAqICAgICAgICAgICAgc3RhcnQgb2Zmc2V0IG9mIHRleHQgdG8gcmVwbGFjZSBOb25lIG9mIHRoZSBvZmZzZXRzIGluY2x1ZGUKCSAqICAgICAgICAgICAgZGVsaW1pdGVycyBvZiBwcmVjZWVkaW5nIGxpbmVzLiBPZmZzZXQgMCBpcyB0aGUgZmlyc3QKCSAqICAgICAgICAgICAgY2hhcmFjdGVyIG9mIHRoZSBkb2N1bWVudC4KCSAqIEBwYXJhbSByZXBsYWNlTGVuZ3RoCgkgKiAgICAgICAgICAgIHN0YXJ0IG9mZnNldCBvZiB0ZXh0IHRvIHJlcGxhY2UKCSAqIEBwYXJhbSBuZXdUZXh0CgkgKiAgICAgICAgICAgIHN0YXJ0IG9mZnNldCBvZiB0ZXh0IHRvIHJlcGxhY2UKCSAqICAgICAgICAgICAgPHA+CgkgKiAgICAgICAgICAgIEltcGxlbWVudG9ycyBoYXZlIHRvIG5vdGlmeSBUZXh0Q2hhbmdlZCBsaXN0ZW5lcnMgYWZ0ZXIgdGhlCgkgKiAgICAgICAgICAgIGNvbnRlbnQgaGFzIGJlZW4gdXBkYXRlZC4gVGhlIFRleHRDaGFuZ2VkRXZlbnQgc2hvdWxkIGJlIHNldAoJICogICAgICAgICAgICBhcyBmb2xsb3dzOgoJICogCgkgKiBldmVudC50eXBlID0gU1dULlRleHRSZXBsYWNlZCBldmVudC5zdGFydCA9IHN0YXJ0IG9mIHRoZSByZXBsYWNlZCB0ZXh0CgkgKiBldmVudC5udW1SZXBsYWNlZExpbmVzID0gbnVtYmVyIG9mIHJlcGxhY2VkIGxpbmVzIGV2ZW50Lm51bU5ld0xpbmVzID0KCSAqIG51bWJlciBvZiBuZXcgbGluZXMgZXZlbnQucmVwbGFjZWRMZW5ndGggPSBsZW5ndGggb2YgdGhlIHJlcGxhY2VkIHRleHQKCSAqIGV2ZW50Lm5ld0xlbmd0aCA9IGxlbmd0aCBvZiB0aGUgbmV3IHRleHQKCSAqIAoJICogTk9URTogbnVtTmV3TGluZXMgaXMgdGhlIG51bWJlciBvZiBpbnNlcnRlZCBsaW5lcyBhbmQgbnVtUmVwbGFjZWRMaW5lcwoJICogaXMgdGhlIG51bWJlciBvZiBkZWxldGVkIGxpbmVzIGJhc2VkIG9uIHRoZSBjaGFuZ2UgdGhhdCBvY2N1cnMKCSAqIHZpc3VhbGx5LiBGb3IgZXhhbXBsZToKCSAqIAoJICogcmVwbGFjZWRUZXh0IG5ld1RleHQgbnVtUmVwbGFjZWRMaW5lcyBudW1OZXdMaW5lcyAiIiAiXG4iIDAgMSAiXG5cbiIKCSAqICJhIiAyIDAgImEiICJcblxuIiAwIDIKCSAqLwoJLyoqCgkgKiBPbmUgb2YgdGhlIEFQSXMgdG8gbWFuaXB1bGF0ZSB0aGUgSVN0cnVjdHVyZWREb2N1bWVudCBpbiB0ZXJtcyBvZiB0ZXh0LgoJICovCglwdWJsaWMgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgcmVwbGFjZVRleHQoT2JqZWN0IHJlcXVlc3RlciwgaW50IHN0YXJ0LCBpbnQgcmVwbGFjZW1lbnRMZW5ndGgsIFN0cmluZyBjaGFuZ2VzKSB7CgkJcmV0dXJuIHJlcGxhY2VUZXh0KHJlcXVlc3Rlciwgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoLCBjaGFuZ2VzLCBmYWxzZSk7Cgl9CgoJcHVibGljIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHJlcGxhY2VUZXh0KE9iamVjdCByZXF1ZXN0ZXIsIGludCBzdGFydCwgaW50IHJlcGxhY2VtZW50TGVuZ3RoLCBTdHJpbmcgY2hhbmdlcywgYm9vbGVhbiBpZ25vcmVSZWFkT25seVNldHRpbmdzKSB7CgkJcmV0dXJuIGludGVybmFsUmVwbGFjZVRleHQocmVxdWVzdGVyLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgsIGNoYW5nZXMsIGlnbm9yZVJlYWRPbmx5U2V0dGluZ3MpOwoJfQoKCXZvaWQgcmVzZXRQYXJzZXIoaW50IHN0YXJ0T2Zmc2V0LCBpbnQgZW5kT2Zmc2V0KSB7CgoJCVJlZ2lvblBhcnNlciBwYXJzZXIgPSBnZXRQYXJzZXIoKTsKCQlJVGV4dFN0b3JlIHRleHRTdG9yZSA9IGdldFN0b3JlKCk7CgkJaWYgKHRleHRTdG9yZSBpbnN0YW5jZW9mIENoYXJTZXF1ZW5jZSkgewoJCQlDaGFyU2VxdWVuY2VSZWFkZXIgc3ViU2V0VGV4dFN0b3JlUmVhZGVyID0gbmV3IENoYXJTZXF1ZW5jZVJlYWRlcigoQ2hhclNlcXVlbmNlKSB0ZXh0U3RvcmUsIHN0YXJ0T2Zmc2V0LCBlbmRPZmZzZXQgLSBzdGFydE9mZnNldCk7CgkJCXBhcnNlci5yZXNldChzdWJTZXRUZXh0U3RvcmVSZWFkZXIsIHN0YXJ0T2Zmc2V0KTsKCQl9CgkJZWxzZSB7CgkJCVN0cmluZyBuZXdOb2RlVGV4dCA9IGdldChzdGFydE9mZnNldCwgZW5kT2Zmc2V0IC0gc3RhcnRPZmZzZXQpOwoJCQlwYXJzZXIucmVzZXQobmV3Tm9kZVRleHQsIHN0YXJ0T2Zmc2V0KTsKCgkJfQoKCX0KCgl2b2lkIHJlc2V0UGFyc2VyKFJlYWRlciByZWFkZXIsIGludCBzdGFydE9mZnNldCkgewoJCVJlZ2lvblBhcnNlciBwYXJzZXIgPSBnZXRQYXJzZXIoKTsKCQlwYXJzZXIucmVzZXQocmVhZGVyLCBzdGFydE9mZnNldCk7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbiNyZXN1bWVQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpCgkgKi8KCXB1YmxpYyB2b2lkIHJlc3VtZVBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCkgewoJCS0tZlN0b3BwZWRDb3VudDsKCQlpZiAoZlN0b3BwZWRDb3VudCA9PSAwICYmIGZSZWVudHJhbmNlQ291bnQgPT0gMCkKCQkJZXhlY3V0ZVBvc3ROb3RpZmljYXRpb25DaGFuZ2VzKCk7Cgl9CgoJLyoqCgkgKiBAZGVwcmVjYXRlZCBpbiBzdXBlcmNsYXNzIGluIDMuMCAtIHVzZSBhIEZpbmRSZXBsYWNlRG9jdW1lbnRBZGFwdGVyCgkgKiAgICAgICAgICAgICBkaXJlY3RseQoJICogQHNlZSBJRG9jdW1lbnQjc2VhcmNoCgkgKi8KCXB1YmxpYyBpbnQgc2VhcmNoKGludCBzdGFydFBvc2l0aW9uLCBTdHJpbmcgZmluZFN0cmluZywgYm9vbGVhbiBmb3J3YXJkU2VhcmNoLCBib29sZWFuIGNhc2VTZW5zaXRpdmUsIGJvb2xlYW4gd2hvbGVXb3JkKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCS8vIChkbXcpIEkgYWRkZWQgdGhpcyB3YXJuaW5nLCB0byBrbm93IGlmIHN0aWxsIGJlaW5nIHVzZWQuIEknbSBub3QKCQkvLyBzdXJlIGl0CgkJLy8gd29ya3MgYXMgZXhwZWN0ZWQgYW55IGxvbmdlci4KCQkvLyBidXQgdGhlIHdhcm5pbmcgc2hvdWxkIGJlIHJlbW92ZWQsIG9uY2Uga25vdy4KCQlMb2dnZXIubG9nKExvZ2dlci5JTkZPLCAiV0FSTklORzogdXNpbmcgdW5zdXBwb3J0ZWQgZGVwcmVjYXRlZCBtZXRob2QgJ3NlYXJjaCciKTsgLy8kTk9OLU5MUy0xJAoJCWludCBvZmZzZXQgPSAtMTsKCQlJUmVnaW9uIG1hdGNoID0gbmV3IEZpbmRSZXBsYWNlRG9jdW1lbnRBZGFwdGVyKHRoaXMpLmZpbmQoc3RhcnRQb3NpdGlvbiwgZmluZFN0cmluZywgZm9yd2FyZFNlYXJjaCwgY2FzZVNlbnNpdGl2ZSwgd2hvbGVXb3JkLCBmYWxzZSk7CgkJaWYgKG1hdGNoICE9IG51bGwpIHsKCQkJb2Zmc2V0ID0gbWF0Y2guZ2V0T2Zmc2V0KCk7CgkJfQoJCXJldHVybiBvZmZzZXQ7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNzZXRUZXh0CgkgKi8KCXB1YmxpYyB2b2lkIHNldChTdHJpbmcgc3RyaW5nKSB7CgkJaWYgKERlYnVnLmRpc3BsYXlJbmZvKSB7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiTm90ZTogSVN0cnVjdHVyZWREb2N1bWVudDo6c2V0VGV4dChTdHJpbmcpIC4uLi4gaXRzIGJldHRlciB0byB1c2Ugc2V0VGV4dChzb3VyY2UsIHN0cmluZykgQVBJIGZvciBzdHJ1Y3R1cmVkRG9jdW1lbnQgdXBkYXRlcyIpOyAvLyROT04tTkxTLTEkCgkJfQoJCXNldFRleHQobnVsbCwgc3RyaW5nKTsKCX0KCgkvKioKCSAqIFRoaXMgbWF5IGJlIG1hcmtlZCBwdWJsaWMsIGJ1dCBzaG91bGQgYmUgcGFja2FnZWQgcHJvdGVjdGVkLCBvbmNlCgkgKiByZWZhY3RvcmluZyBpcyBjb21wbGV0ZSAoaW4gb3RoZXIgd29yZHMsIG5vdCBmb3IgY2xpZW50IHVzZSkuCgkgKi8KCXB1YmxpYyB2b2lkIHNldENhY2hlZERvY3VtZW50UmVnaW9uKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gc3RydWN0dXJlZFJlZ2lvbikgewoJCWlmIChVU0VfTE9DQUxfVEhSRUFEKSB7CgkJCWZDdXJyZW50RG9jdW1uZXRSZWdpb25DYWNoZS5zZXQoc3RydWN0dXJlZFJlZ2lvbik7CgkJfQoJCWVsc2UgewoJCQljYWNoZWREb2N1bWVudFJlZ2lvbiA9IHN0cnVjdHVyZWRSZWdpb247CgkJfQoJfQoKCS8qKgoJICogU2V0cyB0aGUgZG9jdW1lbnQncyBwYXJ0aXRpb25lci4KCSAqIAoJICogQHNlZSBJRG9jdW1lbnRQYXJ0aXRpb25lcgoJICovCglwdWJsaWMgdm9pZCBzZXREb2N1bWVudFBhcnRpdGlvbmVyKElEb2N1bWVudFBhcnRpdGlvbmVyIHBhcnRpdGlvbmVyKSB7CgkJc2V0RG9jdW1lbnRQYXJ0aXRpb25lcihJRG9jdW1lbnRFeHRlbnNpb24zLkRFRkFVTFRfUEFSVElUSU9OSU5HLCBwYXJ0aXRpb25lcik7Cgl9CgoKCXB1YmxpYyB2b2lkIHNldERvY3VtZW50UGFydGl0aW9uZXIoU3RyaW5nIHBhcnRpdGlvbmluZywgSURvY3VtZW50UGFydGl0aW9uZXIgcGFydGl0aW9uZXIpIHsKCQlpZiAocGFydGl0aW9uZXIgPT0gbnVsbCkgewoJCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzICE9IG51bGwpIHsKCQkJCWZEb2N1bWVudFBhcnRpdGlvbmVycy5yZW1vdmUocGFydGl0aW9uaW5nKTsKCQkJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMuc2l6ZSgpID09IDApCgkJCQkJZkRvY3VtZW50UGFydGl0aW9uZXJzID0gbnVsbDsKCQkJfQoJCX0KCQllbHNlIHsKCQkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyA9PSBudWxsKQoJCQkJZkRvY3VtZW50UGFydGl0aW9uZXJzID0gbmV3IEhhc2hNYXAoKTsKCQkJZkRvY3VtZW50UGFydGl0aW9uZXJzLnB1dChwYXJ0aXRpb25pbmcsIHBhcnRpdGlvbmVyKTsKCQl9CgkJRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkRXZlbnQgZXZlbnQgPSBuZXcgRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkRXZlbnQodGhpcyk7CgkJZXZlbnQuc2V0UGFydGl0aW9uQ2hhbmdlKHBhcnRpdGlvbmluZywgMCwgZ2V0TGVuZ3RoKCkpOwoJCWZpcmVEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWQoZXZlbnQpOwoJfQoKCXB1YmxpYyB2b2lkIHNldEVuY29kaW5nTWVtZW50byhFbmNvZGluZ01lbWVudG8gZW5jb2RpbmdNZW1lbnRvKSB7CgkJdGhpcy5lbmNvZGluZ01lbWVudG8gPSBlbmNvZGluZ01lbWVudG87Cgl9CgoJdm9pZCBzZXRGaXJzdERvY3VtZW50UmVnaW9uKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVnaW9uKSB7CgkJZmlyc3REb2N1bWVudFJlZ2lvbiA9IHJlZ2lvbjsKCgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjc2V0SW5pdGlhbExpbmVEZWxpbWl0ZXIoamF2YS5sYW5nLlN0cmluZykKCSAqLwoJcHVibGljIHZvaWQgc2V0SW5pdGlhbExpbmVEZWxpbWl0ZXIoU3RyaW5nIGRlbGltaXRlcikgewoJCS8vIG1ha2Ugc3VyZSBvdXIgcHJlZmVycmVkIGRlbGltaXRlciBpcwoJCS8vIG9uZSBvZiB0aGUgbGVnYWwgb25lcwoJCWlmIChVdGlsaXRpZXMuY29udGFpbnNTdHJpbmcoZ2V0TGVnYWxMaW5lRGVsaW1pdGVycygpLCBkZWxpbWl0ZXIpKSB7CgkJCXByZWZlcmVkRGVsaW1pdGVyID0gZGVsaW1pdGVyOwoJCX0KCQllbHNlIHsKCQkJaWYgKExvZ2dlci5ERUJVR19ET0NVTUVOVCkKCQkJCUxvZ2dlci5sb2coTG9nZ2VyLklORk8sICJBdHRlbXB0IHRvIHNldCBsaW5lZGVsaW1pdGVyIHRvIG5vbi1sZWdhbCBkZWxpbWl0ZXIiKTsgLy8kTk9OLU5MUy0xJCAvLyROT04tTkxTLTIkCgkJCXByZWZlcmVkRGVsaW1pdGVyID0gUGxhdGZvcm1MaW5lRGVsaW1pdGVyOwoJCX0KCX0KCgl2b2lkIHNldExhc3REb2N1bWVudFJlZ2lvbihJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlZ2lvbikgewoJCWxhc3REb2N1bWVudFJlZ2lvbiA9IHJlZ2lvbjsKCgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZERvY3VtZW50I3NldExpbmVEZWxpbWl0ZXIoamF2YS5sYW5nLlN0cmluZykKCSAqLwoJcHVibGljIHZvaWQgc2V0TGluZURlbGltaXRlcihTdHJpbmcgZGVsaW1pdGVyKSB7CgkJc2V0SW5pdGlhbExpbmVEZWxpbWl0ZXIoZGVsaW1pdGVyKTsKCX0KCgkvKioKCSAqIFNldHMgdGhlIGRvY3VtZW50J3MgbGluZSB0cmFja2VyLiBNdXN0IGJlIGNhbGxlZCBhdCB0aGUgYmVnaW5uaW5nIG9mCgkgKiB0aGUgY29uc3RydWN0b3IuCgkgKiAKCSAqIEBwYXJhbSB0cmFja2VyCgkgKiAgICAgICAgICAgIHRoZSBkb2N1bWVudCdzIGxpbmUgdHJhY2tlcgoJICovCglwcml2YXRlIHZvaWQgc2V0TGluZVRyYWNrZXIoSUxpbmVUcmFja2VyIHRyYWNrZXIpIHsKCQlmVHJhY2tlciA9IHRyYWNrZXI7Cgl9CgoJcHVibGljIHZvaWQgc2V0UGFyc2VyKFJlZ2lvblBhcnNlciBuZXdQYXJzZXIpIHsKCQlpbnRlcm5hbF9zZXRQYXJzZXIobmV3UGFyc2VyKTsKCX0KCgkvKioKCSAqIEBwYXJhbSBwb3NpdGlvbk1hbmFnZXIKCSAqICAgICAgICAgICAgVGhlIHBvc2l0aW9uTWFuYWdlciB0byBzZXQuCgkgKi8KCS8vIFRPRE86IG1ha2UgcHJpdmF0ZSBpcyBuZWVkZWQsIGVsc2UgcmVtb3ZlCgl2b2lkIHNldFBvc2l0aW9uTWFuYWdlcihHZW5lcmljUG9zaXRpb25NYW5hZ2VyIHBvc2l0aW9uTWFuYWdlcikgewoJCWZQb3NpdGlvbk1hbmFnZXIgPSBwb3NpdGlvbk1hbmFnZXI7Cgl9CgoJLyoqCgkgKiAKCSAqLwoJcHVibGljIHZvaWQgc2V0UmVQYXJzZXIoSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgbmV3UmVQYXJzZXIpIHsKCQlmUmVQYXJzZXIgPSBuZXdSZVBhcnNlcjsKCQlpZiAoZlJlUGFyc2VyICE9IG51bGwpIHsKCQkJZlJlUGFyc2VyLnNldFN0cnVjdHVyZWREb2N1bWVudCh0aGlzKTsKCQl9Cgl9CgoJLyoqCgkgKiBPbmUgb2YgdGhlIEFQSXMgdG8gbWFuaXB1bGF0ZSB0aGUgSVN0cnVjdHVyZWREb2N1bWVudCBpbiB0ZXJtcyBvZiB0ZXh0LgoJICovCglwdWJsaWMgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgc2V0VGV4dChPYmplY3QgcmVxdWVzdGVyLCBTdHJpbmcgdGhlU3RyaW5nKSB7CgoJCVN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHJlc3VsdCA9IG51bGw7CgoJCXJlc3VsdCA9IHJlcGxhY2VUZXh0KHJlcXVlc3RlciwgMCwgZ2V0TGVuZ3RoKCksIHRoZVN0cmluZywgdHJ1ZSk7CgoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoqCgkgKiBTZXRzIHRoZSBkb2N1bWVudCdzIHRleHQgc3RvcmUuIE11c3QgYmUgY2FsbGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlCgkgKiBjb25zdHJ1Y3Rvci4KCSAqIAoJICogQHBhcmFtIHN0b3JlCgkgKiAgICAgICAgICAgIHRoZSBkb2N1bWVudCdzIHRleHQgc3RvcmUKCSAqLwoJcHJpdmF0ZSB2b2lkIHNldFRleHRTdG9yZShJVGV4dFN0b3JlIHN0b3JlKSB7CgkJZlN0b3JlID0gc3RvcmU7Cgl9CgoJcHVibGljIHZvaWQgc2V0VW5kb01hbmFnZXIoSVN0cnVjdHVyZWRUZXh0VW5kb01hbmFnZXIgdW5kb01hbmFnZXIpIHsKCgkJLy8gaWYgdGhlIHVuZG8gbWFuYWdlciBoYXMgYWxyZWFkeSBiZWVuIHNldCwgdGhlbgoJCS8vIGZhaWwgZmFzdCwgc2luY2UgY2hhbmdpbmcgdGhlIHVuZG8gbWFuYWdlciB3aWxsIGxlYWQKCQkvLyB0byB1bnVzdWFsIHJlc3VsdHMgKG9yIGF0IGxlYXN0IGxvc3Mgb2YgdW5kbyBzdGFjaykuCgkJaWYgKGZVbmRvTWFuYWdlciAhPSBudWxsICYmIGZVbmRvTWFuYWdlciAhPSB1bmRvTWFuYWdlcikgewoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJjYW4gbm90IGNoYW5nZSB1bmRvIG1hbmFnZXIgb25jZSBpdHMgYmVlbiBzZXQiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCQllbHNlIHsKCQkJZlVuZG9NYW5hZ2VyID0gdW5kb01hbmFnZXI7CgkJfQoJfQoKCglwdWJsaWMgdm9pZCBzdGFydFNlcXVlbnRpYWxSZXdyaXRlKGJvb2xlYW4gbm9ybWFsaXplZCkgewoJCUlUZXh0U3RvcmUgc3RvcmUgPSBuZXcgU2VxdWVudGlhbFJld3JpdGVUZXh0U3RvcmUoZ2V0U3RvcmUoKSk7CgkJc2V0VGV4dFN0b3JlKHN0b3JlKTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uI3N0b3BQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpCgkgKi8KCXB1YmxpYyB2b2lkIHN0b3BQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpIHsKCQkrK2ZTdG9wcGVkQ291bnQ7Cgl9CgoKCXB1YmxpYyB2b2lkIHN0b3BTZXF1ZW50aWFsUmV3cml0ZSgpIHsKCQlpZiAoZ2V0U3RvcmUoKSBpbnN0YW5jZW9mIFNlcXVlbnRpYWxSZXdyaXRlVGV4dFN0b3JlKSB7CgkJCVNlcXVlbnRpYWxSZXdyaXRlVGV4dFN0b3JlIHNyd3MgPSAoU2VxdWVudGlhbFJld3JpdGVUZXh0U3RvcmUpIGdldFN0b3JlKCk7CgkJCUlUZXh0U3RvcmUgc291cmNlID0gc3J3cy5nZXRTb3VyY2VTdG9yZSgpOwoJCQlzZXRUZXh0U3RvcmUoc291cmNlKTsKCQkJc3J3cy5kaXNwb3NlKCk7CgkJfQoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgamF2YS5sYW5nLkNoYXJTZXF1ZW5jZSNzdWJTZXF1ZW5jZShpbnQsIGludCkKCSAqLwoJcHVibGljIENoYXJTZXF1ZW5jZSBzdWJTZXF1ZW5jZShpbnQgYXJnMCwgaW50IGFyZzEpIHsKCQlyZXR1cm4gZ2V0KGFyZzAsIGFyZzEpOwoJfQoKCS8qKgoJICogQHBhcmFtIHJlc3VsdAoJICovCglwcml2YXRlIHZvaWQgdXBkYXRlRGVsZXRlZEZpZWxkcyhTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCBldmVudCkgewoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25MaXN0IG9sZFJlZ2lvbnMgPSBldmVudC5nZXRPbGRTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zKCk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBvbGRSZWdpb25zLmdldExlbmd0aCgpOyBpKyspIHsKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBzdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gPSBvbGRSZWdpb25zLml0ZW0oaSk7CgkJCXN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbi5zZXREZWxldGVkKHRydWUpOwoJCX0KCgl9CgoJLyoqCgkgKiBDYWxsZWQgYnkgcmUtcGFyc2VyLiBOb3RlOiB0aGlzIG1ldGhvZCBtYXkgYmUgInB1YmxpYyIgYnV0IHNob3VsZCBvbmx5CgkgKiBiZSBjYWxsZWQgYnkgcmUtcGFyc2VycyBpbiB0aGUgcmlnaHQgY2lyY3Vtc3RhbmNlcy4KCSAqLwoJcHVibGljIHZvaWQgdXBkYXRlRG9jdW1lbnREYXRhKGludCBzdGFydCwgaW50IGxlbmd0aFRvUmVwbGFjZSwgU3RyaW5nIGNoYW5nZXMpIHsKCQlzdG9wUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCQlnZXRTdG9yZSgpLnJlcGxhY2Uoc3RhcnQsIGxlbmd0aFRvUmVwbGFjZSwgY2hhbmdlcyk7CgkJdHJ5IHsKCQkJZ2V0VHJhY2tlcigpLnJlcGxhY2Uoc3RhcnQsIGxlbmd0aFRvUmVwbGFjZSwgY2hhbmdlcyk7CgkJfQoKCQljYXRjaCAoQmFkTG9jYXRpb25FeGNlcHRpb24gZSkgewoJCQkvLyBzaG91bGQgYmUgaW1wb3NzaWJsZSBoZXJlLCBidXQgd2lsbCBsb2cgZm9yIG5vdwoJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGUpOwoJCX0KCQlpZiAoZlBvc2l0aW9uTWFuYWdlciAhPSBudWxsKSB7CgkJCWZQb3NpdGlvbk1hbmFnZXIudXBkYXRlUG9zaXRpb25zKG5ldyBEb2N1bWVudEV2ZW50KHRoaXMsIHN0YXJ0LCBsZW5ndGhUb1JlcGxhY2UsIGNoYW5nZXMpKTsKCQl9CgkJZk1vZGlmaWNhdGlvblN0YW1wKys7CgkJcmVzdW1lUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCX0KCglwcml2YXRlIFN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHVwZGF0ZU1vZGVsKE9iamVjdCByZXF1ZXN0ZXIsIGludCBzdGFydCwgaW50IGxlbmd0aFRvUmVwbGFjZSwgU3RyaW5nIGNoYW5nZXMpIHsKCQlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCByZXN1bHQgPSBudWxsOwoJCUlTdHJ1Y3R1cmVkVGV4dFJlUGFyc2VyIHJlUGFyc2VyID0gZ2V0UmVQYXJzZXIoKTsKCQkvLyBpbml0aWFsaXplIHRoZSBJU3RydWN0dXJlZFRleHRSZVBhcnNlciB3aXRoIHRoZSBzdGFuZGFyZCBkYXRhCgkJLy8gdGhhdCdzCgkJLy8gYWx3YXlzIG5lZWRlZAoJCXJlUGFyc2VyLmluaXRpYWxpemUocmVxdWVzdGVyLCBzdGFydCwgbGVuZ3RoVG9SZXBsYWNlLCBjaGFuZ2VzKTsKCQlyZXN1bHQgPSByZVBhcnNlci5yZXBhcnNlKCk7CgkJLy8gaWYgcmVzdWx0IGlzIG51bGwgYXQgdGhpcyBwb2ludCwgdGhlbiB0aGVyZSBtdXN0IGJlIGFuIGVycm9yLCBzaW5jZQoJCS8vIGV2ZW4gaWYgdGhlcmUKCQkvLyB3YXMgbm8gY2hhbmdlIChlaXRoZXIgZGlzYWxsb3cgZHVlIHRvIHJlYWRvbmx5LCBvciBhIHBlcnNvbiBwYXN0ZWQKCQkvLyB0aGUgc2FtZSB0aGluZwoJCS8vIHRoZXkgaGFkIHNlbGVjdGVkKSB0aGVuIGEgIk5vQ2hhbmdlIiBldmVudCBzaG91bGQgaGF2ZSBiZWVuIGZpcmVkLgoJCUFzc2VydC5pc05vdE51bGwocmVzdWx0LCAibm8gc3RydWN0dXJlZERvY3VtZW50IGV2ZW50IHdhcyBjcmVhdGVkIGluIElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OnVwZGF0ZVN0cnVjdHVyZWREb2N1bWVudCIpOyAvLyROT04tTkxTLTEkCgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5kb2N1bWVudC5JRW5jb2RlZERvY3VtZW50I2dldFByZWZlcnJlZExpbmVEZWxpbWl0ZXIoKQoJICovCglwdWJsaWMgU3RyaW5nIGdldFByZWZlcnJlZExpbmVEZWxpbWl0ZXIoKSB7CgkJcmV0dXJuIGdldERlZmF1bHRMaW5lRGVsaW1pdGVyKCk7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZG9jdW1lbnQuSUVuY29kZWREb2N1bWVudCNzZXRQcmVmZXJyZWRMaW5lRGVsaW1pdGVyKGphdmEubGFuZy5TdHJpbmcpCgkgKi8KCXB1YmxpYyB2b2lkIHNldFByZWZlcnJlZExpbmVEZWxpbWl0ZXIoU3RyaW5nIHByb2JhYmxlTGluZURlbGltaXRlcikgewoJCXNldEluaXRpYWxMaW5lRGVsaW1pdGVyKHByb2JhYmxlTGluZURlbGltaXRlcik7CgoJfQoKCgkvKioKCSAqIENsYXNzIHdoaWNoIGltcGxlbWVudHMgdGhlIHJld3JpdGFibGUgc2Vzc2lvbiBmb3IgdGhlIFNTRS4KCSAqIAoJICovCgljbGFzcyBTdHJ1Y3R1cmVkRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBleHRlbmRzIERvY3VtZW50UmV3cml0ZVNlc3Npb24gewoKCQkvKioKCQkgKiBDcmVhdGVzIGEgbmV3IHNlc3Npb24uCgkJICogCgkJICogQHBhcmFtIHNlc3Npb25UeXBlCgkJICogICAgICAgICAgICB0aGUgdHlwZSBvZiB0aGlzIHNlc3Npb24KCQkgKi8KCQlwcm90ZWN0ZWQgU3RydWN0dXJlZERvY3VtZW50UmV3cml0ZVNlc3Npb24oRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUgc2Vzc2lvblR5cGUpIHsKCQkJc3VwZXIoc2Vzc2lvblR5cGUpOwoJCX0KCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNzdGFydFJld3JpdGVTZXNzaW9uKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUpCgkgKi8KCXB1YmxpYyBEb2N1bWVudFJld3JpdGVTZXNzaW9uIHN0YXJ0UmV3cml0ZVNlc3Npb24oRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUgc2Vzc2lvblR5cGUpIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24gewoJCS8vIGRlbGVnYXRlIHRvIHN1Yi1jbGFzcywgc28gVUkgdGhyZWFkaW5nIGlzIGhhbmRsZWQgY29ycmVjdGx5CgkJcmV0dXJuIGludGVybmFsU3RhcnRSZXdyaXRlU2Vzc2lvbihzZXNzaW9uVHlwZSk7Cgl9CgoJLyoqCgkgKiBOT1QtQVBJLiBGaW5hbCBwcm90ZWN0ZWQgc28gY2xpZW50cyBtYXkgY2FsbCB0aGlzIG1ldGhvZCBpZiBuZWVkZWQsIGJ1dAoJICogY2Fubm90IG92ZXJyaWRlLgoJICogCgkgKiBAcGFyYW0gc2Vzc2lvblR5cGUKCSAqIEByZXR1cm4KCSAqIEB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uCgkgKi8KCWZpbmFsIHByb3RlY3RlZCBEb2N1bWVudFJld3JpdGVTZXNzaW9uIGludGVybmFsU3RhcnRSZXdyaXRlU2Vzc2lvbihEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZSBzZXNzaW9uVHlwZSkgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiB7CgkJaWYgKGdldEFjdGl2ZVJld3JpdGVTZXNzaW9uKCkgIT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigpOwoKCQlEb2N1bWVudFJld3JpdGVTZXNzaW9uIHNlc3Npb24gPSBuZXcgU3RydWN0dXJlZERvY3VtZW50UmV3cml0ZVNlc3Npb24oc2Vzc2lvblR5cGUpOwoJCURvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudCBldmVudCA9IG5ldyBEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQodGhpcywgc2Vzc2lvbiwgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50LlNFU1NJT05fU1RBUlQpOwoJCWZpcmVEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQoZXZlbnQpOwoKCQlJTGluZVRyYWNrZXIgdHJhY2tlciA9IGdldFRyYWNrZXIoKTsKCQlpZiAodHJhY2tlciBpbnN0YW5jZW9mIElMaW5lVHJhY2tlckV4dGVuc2lvbikgewoJCQlJTGluZVRyYWNrZXJFeHRlbnNpb24gZXh0ZW5zaW9uID0gKElMaW5lVHJhY2tlckV4dGVuc2lvbikgdHJhY2tlcjsKCQkJZXh0ZW5zaW9uLnN0YXJ0UmV3cml0ZVNlc3Npb24oc2Vzc2lvbik7CgkJfQoKCQlpZiAoRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUuU0VRVUVOVElBTCA9PSBzZXNzaW9uVHlwZSkKCQkJc3RhcnRTZXF1ZW50aWFsUmV3cml0ZShmYWxzZSk7CgkJZWxzZSBpZiAoRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUuU1RSSUNUTFlfU0VRVUVOVElBTCA9PSBzZXNzaW9uVHlwZSkKCQkJc3RhcnRTZXF1ZW50aWFsUmV3cml0ZSh0cnVlKTsKCgkJZkFjdGl2ZVJld3JpdGVTZXNzaW9uID0gc2Vzc2lvbjsKCQlyZXR1cm4gc2Vzc2lvbjsKCX0KCgoJcHVibGljIHZvaWQgc3RvcFJld3JpdGVTZXNzaW9uKERvY3VtZW50UmV3cml0ZVNlc3Npb24gc2Vzc2lvbikgewoJCS8vIGRlbGVnYXRlIHRvIHN1Yi1jbGFzcywgc28gVUkgdGhyZWFkaW5nIGlzIGhhbmRsZWQgY29ycmVjdGx5CgkJaW50ZXJuYWxTdG9wUmV3cml0ZVNlc3Npb24oc2Vzc2lvbik7Cgl9CgoJLyoqCgkgKiBOT1QtQVBJLiBGaW5hbCBwcm90ZWN0ZWQgc28gY2xpZW50cyBtYXkgY2FsbCB0aGlzIG1ldGhvZCBpZiBuZWVkZWQsIGJ1dAoJICogY2Fubm90IG92ZXJyaWRlLgoJICogCgkgKiBAcGFyYW0gc2Vzc2lvbgoJICovCglmaW5hbCBwcm90ZWN0ZWQgdm9pZCBpbnRlcm5hbFN0b3BSZXdyaXRlU2Vzc2lvbihEb2N1bWVudFJld3JpdGVTZXNzaW9uIHNlc3Npb24pIHsKCQlpZiAoZkFjdGl2ZVJld3JpdGVTZXNzaW9uID09IHNlc3Npb24pIHsKCQkJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUgc2Vzc2lvblR5cGUgPSBzZXNzaW9uLmdldFNlc3Npb25UeXBlKCk7CgkJCWlmIChEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZS5TRVFVRU5USUFMID09IHNlc3Npb25UeXBlIHx8IERvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlLlNUUklDVExZX1NFUVVFTlRJQUwgPT0gc2Vzc2lvblR5cGUpCgkJCQlzdG9wU2VxdWVudGlhbFJld3JpdGUoKTsKCgkJCUlMaW5lVHJhY2tlciB0cmFja2VyID0gZ2V0VHJhY2tlcigpOwoJCQlpZiAodHJhY2tlciBpbnN0YW5jZW9mIElMaW5lVHJhY2tlckV4dGVuc2lvbikgewoJCQkJSUxpbmVUcmFja2VyRXh0ZW5zaW9uIGV4dGVuc2lvbiA9IChJTGluZVRyYWNrZXJFeHRlbnNpb24pIHRyYWNrZXI7CgkJCQlleHRlbnNpb24uc3RvcFJld3JpdGVTZXNzaW9uKHNlc3Npb24sIGdldCgpKTsKCQkJfQoKCQkJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50IGV2ZW50ID0gbmV3IERvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudCh0aGlzLCBzZXNzaW9uLCBEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQuU0VTU0lPTl9TVE9QKTsKCQkJZmlyZURvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudChldmVudCk7CgkJCWZBY3RpdmVSZXdyaXRlU2Vzc2lvbiA9IG51bGw7CgkJfQoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I2dldEFjdGl2ZVJld3JpdGVTZXNzaW9uKCkKCSAqLwoJcHVibGljIERvY3VtZW50UmV3cml0ZVNlc3Npb24gZ2V0QWN0aXZlUmV3cml0ZVNlc3Npb24oKSB7CgkJcmV0dXJuIGZBY3RpdmVSZXdyaXRlU2Vzc2lvbjsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNhZGREb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIob3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCBhZGREb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIoSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgkJCUFzc2VydC5pc05vdE51bGwobGlzdGVuZXIpOwoJCQlpZiAoZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMgPT0gbnVsbCkgewoJCQkJZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMgPSBuZXcgQXJyYXlMaXN0KDEpOwoJCQl9CgkJCWlmICghZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMuY29udGFpbnMobGlzdGVuZXIpKQoJCQkJZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTsKCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjcmVtb3ZlRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKElEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJQXNzZXJ0LmlzTm90TnVsbChsaXN0ZW5lcik7CgkJCWlmIChmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycyAhPSBudWxsKQoJCQkJZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMucmVtb3ZlKGxpc3RlbmVyKTsKCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjcmVwbGFjZShpbnQsIGludCwKCSAqICAgICAgamF2YS5sYW5nLlN0cmluZywgbG9uZykKCSAqLwoJcHVibGljIHZvaWQgcmVwbGFjZShpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoLCBTdHJpbmcgdGV4dCwgbG9uZyBtb2RpZmljYXRpb25TdGFtcCkgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXBsYWNlVGV4dCh0aGlzLCBvZmZzZXQsIGxlbmd0aCwgdGV4dCk7CgkJZk1vZGlmaWNhdGlvblN0YW1wID0gbW9kaWZpY2F0aW9uU3RhbXA7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjc2V0KGphdmEubGFuZy5TdHJpbmcsCgkgKiAgICAgIGxvbmcpCgkgKi8KCXB1YmxpYyB2b2lkIHNldChTdHJpbmcgdGV4dCwgbG9uZyBtb2RpZmljYXRpb25TdGFtcCkgewoJCS8vIGJ1ZyAxNTEwNjkgLSBvdmVyd3JpdGUgcmVhZCBvbmx5IHJlZ2lvbnMgd2hlbiBzZXR0aW5nIGVudGlyZSBkb2N1bWVudAoJCSByZXBsYWNlVGV4dChudWxsLCAwLCBnZXRMZW5ndGgoKSwgdGV4dCwgdHJ1ZSk7CgoJCWZNb2RpZmljYXRpb25TdGFtcCA9IG1vZGlmaWNhdGlvblN0YW1wOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I2dldE1vZGlmaWNhdGlvblN0YW1wKCkKCSAqLwoJcHVibGljIGxvbmcgZ2V0TW9kaWZpY2F0aW9uU3RhbXAoKSB7CgkJcmV0dXJuIGZNb2RpZmljYXRpb25TdGFtcDsKCX0KCgkvKioKCSAqIEZpcmVzIGFuIGV2ZW50LCBhcyBzcGVjaWZpZWQsIHRvIHRoZSBhc3NvY2lhdGVkIGxpc3RlbmVycy4KCSAqIAoJICogQHBhcmFtIGV2ZW50CgkgKiAgICAgICAgICAgIFRoZSBldmVudCB0byBmaXJlLCBlaXRoZXIgYSBzdGFydCBvciBzdG9wIGV2ZW50LgoJICovCglwcml2YXRlIHZvaWQgZmlyZURvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudChEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQgZXZlbnQpIHsKCQlpZiAoZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMgPT0gbnVsbCB8fCBmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycy5zaXplKCkgPT0gMCkKCQkJcmV0dXJuOwoKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzKTsKCQlJdGVyYXRvciBlID0gbGlzdC5pdGVyYXRvcigpOwoJCXdoaWxlIChlLmhhc05leHQoKSkgewoJCQlJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyIGwgPSAoSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcikgZS5uZXh0KCk7CgkJCWwuZG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkNoYW5nZWQoZXZlbnQpOwoJCX0KCX0KfQo=